about summary refs log tree commit diff
path: root/src/devices/wifi/tests/test-devices-wifi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/wifi/tests/test-devices-wifi.c')
-rw-r--r--src/devices/wifi/tests/test-devices-wifi.c1519
1 files changed, 1519 insertions, 0 deletions
diff --git a/src/devices/wifi/tests/test-devices-wifi.c b/src/devices/wifi/tests/test-devices-wifi.c
new file mode 100644
index 00000000..a0b3e17f
--- /dev/null
+++ b/src/devices/wifi/tests/test-devices-wifi.c
@@ -0,0 +1,1519 @@
+/*
+ * 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, 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ */
+
+#include "nm-default.h"
+
+#include "devices/wifi/nm-wifi-utils.h"
+#include "nm-core-internal.h"
+
+#include "nm-test-utils-core.h"
+
+#define DEBUG 1
+
+/*****************************************************************************/
+
+#define COMPARE(src, expected, success, error, edomain, ecode) \
+{ \
+	if (expected) { \
+		if (!success) { \
+			g_assert (error != NULL); \
+			g_warning ("Failed to complete connection: %s", error->message); \
+		} \
+		g_assert (success == TRUE); \
+		g_assert (error == NULL); \
+\
+		success = nm_connection_compare (src, expected, NM_SETTING_COMPARE_FLAG_EXACT); \
+		if (success == FALSE && DEBUG) { \
+			g_print ("\n- COMPLETED ---------------------------------\n"); \
+			nm_connection_dump (src); \
+			g_print ("+ EXPECTED ++++++++++++++++++++++++++++++++++++\n"); \
+			nm_connection_dump (expected); \
+			g_print ("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); \
+		} \
+		g_assert (success == TRUE); \
+	} else { \
+		if (success) { \
+			g_print ("\n- COMPLETED ---------------------------------\n"); \
+			nm_connection_dump (src); \
+		} \
+		g_assert (success == FALSE); \
+		g_assert_error (error, edomain, ecode); \
+	} \
+ \
+	g_clear_error (&error); \
+}
+
+static gboolean
+complete_connection (const char *ssid,
+                     const char *bssid,
+                     NM80211Mode mode,
+                     guint32 flags,
+                     guint32 wpa_flags,
+                     guint32 rsn_flags,
+                     gboolean lock_bssid,
+                     NMConnection *src,
+                     GError **error)
+{
+	gs_unref_bytes GBytes *ssid_b = NULL;
+	NMSettingWireless *s_wifi;
+
+	/* Add a wifi setting if one doesn't exist */
+	s_wifi = nm_connection_get_setting_wireless (src);
+	if (!s_wifi) {
+		s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+		nm_connection_add_setting (src, NM_SETTING (s_wifi));
+	}
+
+	ssid_b = g_bytes_new (ssid, strlen (ssid));
+
+	return nm_wifi_utils_complete_connection (ssid_b,
+	                                          bssid,
+	                                          mode,
+	                                          0,
+	                                          flags,
+	                                          wpa_flags,
+	                                          rsn_flags,
+	                                          src,
+	                                          lock_bssid,
+	                                          error);
+}
+
+typedef struct {
+	const char *key;
+	const char *str;
+	guint32     uint;
+} KeyData;
+
+static void
+set_items (NMSetting *setting, const KeyData *items)
+{
+	const KeyData *item;
+	GParamSpec *pspec;
+	GBytes *tmp;
+
+	for (item = items; item && item->key; item++) {
+		g_assert (item->key);
+		pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), item->key);
+		g_assert (pspec);
+
+		if (pspec->value_type == G_TYPE_STRING) {
+			g_assert (item->uint == 0);
+			if (item->str)
+				g_object_set (G_OBJECT (setting), item->key, item->str, NULL);
+		} else if (pspec->value_type == G_TYPE_UINT) {
+			g_assert (item->str == NULL);
+			g_object_set (G_OBJECT (setting), item->key, item->uint, NULL);
+		} else if (pspec->value_type == G_TYPE_INT) {
+			int foo = (int) item->uint;
+
+			g_assert (item->str == NULL);
+			g_object_set (G_OBJECT (setting), item->key, foo, NULL);
+		} else if (pspec->value_type == G_TYPE_BOOLEAN) {
+			gboolean foo = !! (item->uint);
+
+			g_assert (item->str == NULL);
+			g_object_set (G_OBJECT (setting), item->key, foo, NULL);
+		} else if (pspec->value_type == G_TYPE_BYTES) {
+			g_assert (item->str);
+			tmp = g_bytes_new (item->str, strlen (item->str));
+			g_object_set (G_OBJECT (setting), item->key, tmp, NULL);
+			g_bytes_unref (tmp);
+		} else {
+			/* Special types, check based on property name */
+			if (!strcmp (item->key, NM_SETTING_WIRELESS_SECURITY_PROTO))
+				nm_setting_wireless_security_add_proto (NM_SETTING_WIRELESS_SECURITY (setting), item->str);
+			else if (!strcmp (item->key, NM_SETTING_WIRELESS_SECURITY_PAIRWISE))
+				nm_setting_wireless_security_add_pairwise (NM_SETTING_WIRELESS_SECURITY (setting), item->str);
+			else if (!strcmp (item->key, NM_SETTING_WIRELESS_SECURITY_GROUP))
+				nm_setting_wireless_security_add_group (NM_SETTING_WIRELESS_SECURITY (setting), item->str);
+			else if (!strcmp (item->key, NM_SETTING_802_1X_EAP))
+				nm_setting_802_1x_add_eap_method (NM_SETTING_802_1X (setting), item->str);
+		}
+	}
+}
+
+static NMSettingWireless *
+fill_wifi_empty (NMConnection *connection)
+{
+	NMSettingWireless *s_wifi;
+
+	s_wifi = nm_connection_get_setting_wireless (connection);
+	if (!s_wifi) {
+		s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+		nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+	}
+	return s_wifi;
+}
+
+static NMSettingWireless *
+fill_wifi (NMConnection *connection, const KeyData items[])
+{
+	NMSettingWireless *s_wifi;
+
+	s_wifi = nm_connection_get_setting_wireless (connection);
+	if (!s_wifi) {
+		s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+		nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+	}
+
+	set_items (NM_SETTING (s_wifi), items);
+	return s_wifi;
+}
+
+static NMSettingWirelessSecurity *
+fill_wsec (NMConnection *connection, const KeyData items[])
+{
+	NMSettingWirelessSecurity *s_wsec;
+
+	s_wsec = nm_connection_get_setting_wireless_security (connection);
+	if (!s_wsec) {
+		s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+		nm_connection_add_setting (connection, NM_SETTING (s_wsec));
+	}
+
+	set_items (NM_SETTING (s_wsec), items);
+	return s_wsec;
+}
+
+static NMSetting8021x *
+fill_8021x (NMConnection *connection, const KeyData items[])
+{
+	NMSetting8021x *s_8021x;
+
+	s_8021x = nm_connection_get_setting_802_1x (connection);
+	if (!s_8021x) {
+		s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+		nm_connection_add_setting (connection, NM_SETTING (s_8021x));
+	}
+
+	set_items (NM_SETTING (s_8021x), items);
+	return s_8021x;
+}
+
+static NMConnection *
+create_basic (const char *ssid,
+              const char *bssid,
+              NM80211Mode mode)
+{
+	NMConnection *connection;
+	NMSettingWireless *s_wifi = NULL;
+	GBytes *tmp;
+
+	connection = nm_simple_connection_new ();
+
+	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+
+	/* SSID */
+	tmp = g_bytes_new (ssid, strlen (ssid));
+	g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_SSID, tmp, NULL);
+	g_bytes_unref (tmp);
+
+	/* BSSID */
+	if (bssid)
+		g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_BSSID, bssid, NULL);
+
+	if (mode == NM_802_11_MODE_INFRA)
+		g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_MODE, "infrastructure", NULL);
+	else if (mode == NM_802_11_MODE_ADHOC)
+		g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_MODE, "adhoc", NULL);
+	else
+		g_assert_not_reached ();
+
+	return connection;
+}
+
+/*****************************************************************************/
+
+static void
+test_lock_bssid (void)
+{
+	NMConnection *src, *expected;
+	const char *bssid = "01:02:03:04:05:06";
+	const char *ssid = "blahblah";
+	gboolean success;
+	GError *error = NULL;
+
+	src = nm_simple_connection_new ();
+	success = complete_connection (ssid, bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE,
+	                               NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE,
+	                               TRUE,
+	                               src, &error);
+	expected = create_basic (ssid, bssid, NM_802_11_MODE_INFRA);
+	COMPARE (src, expected, success, error, 0, 0);
+
+	g_object_unref (src);
+	g_object_unref (expected);
+}
+
+/*****************************************************************************/
+
+static void
+test_open_ap_empty_connection (void)
+{
+	NMConnection *src, *expected;
+	const char *bssid = "01:02:03:04:05:06";
+	const char *ssid = "blahblah";
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that an empty source connection is correctly filled with the
+	 * SSID and Infra modes of the given AP details.
+	 */
+
+	src = nm_simple_connection_new ();
+	success = complete_connection (ssid, bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE,
+	                               NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE,
+	                               FALSE,
+	                               src, &error);
+	expected = create_basic (ssid, NULL, NM_802_11_MODE_INFRA);
+	COMPARE (src, expected, success, error, 0, 0);
+
+	g_object_unref (src);
+	g_object_unref (expected);
+}
+
+/*****************************************************************************/
+
+static void
+test_open_ap_leap_connection_1 (gconstpointer add_wifi)
+{
+	NMConnection *src;
+	const char *bssid = "01:02:03:04:05:06";
+	const KeyData src_wsec[] = { { NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, "Bill Smith", 0 }, { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that a basic connection filled with a LEAP username is
+	 * rejected when completion is attempted with an open AP.  LEAP requires
+	 * the AP to have the Privacy bit set.
+	 */
+
+	src = nm_simple_connection_new ();
+	if (add_wifi)
+		fill_wifi_empty (src);
+	fill_wsec (src, src_wsec);
+
+	success = complete_connection ("blahblah", bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE,
+	                               NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE,
+	                               FALSE,
+	                               src, &error);
+	/* We expect failure */
+	COMPARE (src, NULL, success, error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING);
+
+	g_object_unref (src);
+}
+
+/*****************************************************************************/
+
+static void
+test_open_ap_leap_connection_2 (void)
+{
+	NMConnection *src;
+	const char *bssid = "01:02:03:04:05:06";
+	const KeyData src_wsec[] = { { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 }, { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that a basic connection specifying IEEE8021x security (ie, Dynamic
+	 * WEP or LEAP) is rejected when completion is attempted with an open AP.
+	 */
+
+	src = nm_simple_connection_new ();
+	fill_wifi_empty (src);
+	fill_wsec (src, src_wsec);
+
+	success = complete_connection ("blahblah", bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE,
+	                               NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE,
+	                               FALSE,
+	                               src, &error);
+	/* We expect failure */
+	COMPARE (src, NULL, success, error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING);
+
+	g_object_unref (src);
+}
+
+/*****************************************************************************/
+
+static void
+test_open_ap_wep_connection (gconstpointer add_wifi)
+{
+	NMConnection *src;
+	const char *bssid = "01:02:03:04:05:06";
+	const KeyData src_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, "11111111111111111111111111", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, NULL, 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that a static WEP connection is rejected when completion is
+	 * attempted with an open AP.
+	 */
+
+	src = nm_simple_connection_new ();
+	if (add_wifi)
+		fill_wifi_empty (src);
+	fill_wsec (src, src_wsec);
+	success = complete_connection ("blahblah", bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE,
+	                               NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE,
+	                               FALSE,
+	                               src, &error);
+	/* We expect failure */
+	COMPARE (src, NULL, success, error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING);
+
+	g_object_unref (src);
+}
+
+/*****************************************************************************/
+
+static void
+test_ap_wpa_psk_connection_base (const char *key_mgmt,
+                                 const char *auth_alg,
+                                 guint32 flags,
+                                 guint32 wpa_flags,
+                                 guint32 rsn_flags,
+                                 gboolean add_wifi,
+                                 guint error_code,
+                                 NMConnection *expected)
+{
+	NMConnection *src;
+	const char *ssid = "blahblah";
+	const char *bssid = "01:02:03:04:05:06";
+	const KeyData exp_wifi[] = {
+		{ NM_SETTING_WIRELESS_SSID, ssid, 0 },
+		{ NM_SETTING_WIRELESS_MODE, "infrastructure", 0 },
+		{ NULL } };
+	const KeyData both_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, key_mgmt, 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, auth_alg, 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_PSK, "asdfasdfasdfasdfasdfafs", 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	src = nm_simple_connection_new ();
+	if (add_wifi)
+		fill_wifi_empty (src);
+	fill_wsec (src, both_wsec);
+	success = complete_connection (ssid, bssid, NM_802_11_MODE_INFRA,
+	                               flags, wpa_flags, rsn_flags,
+	                               FALSE, src, &error);
+	if (expected) {
+		fill_wifi (expected, exp_wifi);
+		fill_wsec (expected, both_wsec);
+	}
+	COMPARE (src, expected, success, error, NM_CONNECTION_ERROR, error_code);
+
+	g_object_unref (src);
+}
+
+static void
+test_open_ap_wpa_psk_connection_1 (void)
+{
+	/* Test that a WPA-PSK connection filling only the PSK itself and *not*
+	 * filling the wifi setting is rejected when completion is attempted with
+	 * an open AP.
+	 */
+	test_ap_wpa_psk_connection_base (NULL, NULL,
+	                                 NM_802_11_AP_FLAGS_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 FALSE,
+	                                 NM_CONNECTION_ERROR_INVALID_SETTING,
+	                                 NULL);
+}
+
+static void
+test_open_ap_wpa_psk_connection_2 (void)
+{
+	/* Test that a WPA-PSK connection filling only the PSK itself and also
+	 * filling the wifi setting is rejected when completion is attempted with
+	 * an open AP.
+	 */
+	test_ap_wpa_psk_connection_base (NULL, NULL,
+	                                 NM_802_11_AP_FLAGS_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 TRUE,
+	                                 NM_CONNECTION_ERROR_INVALID_SETTING,
+	                                 NULL);
+}
+
+static void
+test_open_ap_wpa_psk_connection_3 (void)
+{
+	/* Test that a WPA-PSK connection filling the PSK and setting the auth alg
+	 * to 'open' is rejected when completion is attempted with an open AP.
+	 */
+	test_ap_wpa_psk_connection_base (NULL, "open",
+	                                 NM_802_11_AP_FLAGS_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 FALSE,
+	                                 NM_CONNECTION_ERROR_INVALID_SETTING,
+	                                 NULL);
+}
+
+static void
+test_open_ap_wpa_psk_connection_4 (void)
+{
+	/* Test that a WPA-PSK connection filling the PSK and setting the auth alg
+	 * to 'shared' is rejected when completion is attempted with an open AP.
+	 * Shared auth cannot be used with WPA.
+	 */
+	test_ap_wpa_psk_connection_base (NULL, "shared",
+	                                 NM_802_11_AP_FLAGS_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 FALSE,
+	                                 NM_CONNECTION_ERROR_INVALID_SETTING,
+	                                 NULL);
+}
+
+static void
+test_open_ap_wpa_psk_connection_5 (void)
+{
+	/* Test that a WPA-PSK connection filling the PSK, the auth algorithm, and
+	 * key management is rejected when completion is attempted with an open AP.
+	 */
+	test_ap_wpa_psk_connection_base ("wpa-psk", "open",
+	                                 NM_802_11_AP_FLAGS_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 FALSE,
+	                                 NM_CONNECTION_ERROR_INVALID_SETTING,
+	                                 NULL);
+}
+
+/*****************************************************************************/
+
+static void
+test_ap_wpa_eap_connection_base (const char *key_mgmt,
+                                 const char *auth_alg,
+                                 guint32 flags,
+                                 guint32 wpa_flags,
+                                 guint32 rsn_flags,
+                                 gboolean add_wifi,
+                                 guint error_code)
+{
+	NMConnection *src;
+	const char *bssid = "01:02:03:04:05:06";
+	const KeyData src_empty[] = { { NULL } };
+	const KeyData src_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, key_mgmt, 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, auth_alg, 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	src = nm_simple_connection_new ();
+	if (add_wifi)
+		fill_wifi_empty (src);
+	fill_wsec (src, src_wsec);
+	fill_8021x (src, src_empty);
+	success = complete_connection ("blahblah", bssid, NM_802_11_MODE_INFRA,
+	                               flags, wpa_flags, rsn_flags,
+	                               FALSE, src, &error);
+	/* Failure expected */
+	COMPARE (src, NULL, success, error, NM_CONNECTION_ERROR, error_code);
+
+	g_object_unref (src);
+}
+
+enum {
+	IDX_NONE = 0,
+	IDX_OPEN,
+	IDX_PRIV,
+	IDX_WPA_PSK_PTKIP_GTKIP,
+	IDX_WPA_PSK_PTKIP_PCCMP_GTKIP,
+	IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP,
+	IDX_WPA_RSN_PSK_PCCMP_GCCMP,
+	IDX_RSN_PSK_PCCMP_GCCMP,
+	IDX_RSN_PSK_PTKIP_PCCMP_GTKIP,
+	IDX_WPA_8021X,
+	IDX_RSN_8021X,
+};
+
+static guint32
+flags_for_idx (guint32 idx)
+{
+	if (idx == IDX_OPEN)
+		return NM_802_11_AP_FLAGS_NONE;
+	else if (   idx == IDX_PRIV
+	         || idx == IDX_WPA_PSK_PTKIP_GTKIP
+	         || idx == IDX_WPA_PSK_PTKIP_PCCMP_GTKIP
+	         || idx == IDX_RSN_PSK_PCCMP_GCCMP
+	         || idx == IDX_RSN_PSK_PTKIP_PCCMP_GTKIP
+	         || idx == IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP
+	         || idx == IDX_WPA_RSN_PSK_PCCMP_GCCMP
+	         || idx == IDX_WPA_8021X
+	         || idx == IDX_RSN_8021X)
+		return NM_802_11_AP_FLAGS_PRIVACY;
+	else
+		g_assert_not_reached ();
+}
+
+static guint32
+wpa_flags_for_idx (guint32 idx)
+{
+	if (idx == IDX_OPEN || idx == IDX_PRIV ||  idx == IDX_RSN_8021X
+	    || idx == IDX_RSN_PSK_PCCMP_GCCMP || idx == IDX_RSN_PSK_PTKIP_PCCMP_GTKIP)
+		return NM_802_11_AP_SEC_NONE;
+	else if (idx == IDX_WPA_PSK_PTKIP_GTKIP)
+		return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_PSK;
+	else if (idx == IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP)
+		return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_PSK;
+	else if (NM_IN_SET (idx, IDX_WPA_PSK_PTKIP_PCCMP_GTKIP, IDX_WPA_RSN_PSK_PCCMP_GCCMP))
+		return NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_CCMP | NM_802_11_AP_SEC_KEY_MGMT_PSK;
+	else if (idx == IDX_WPA_8021X)
+		return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_802_1X;
+	else
+		g_assert_not_reached ();
+}
+
+static guint32
+rsn_flags_for_idx (guint32 idx)
+{
+	if (idx == IDX_OPEN || idx == IDX_PRIV || idx == IDX_WPA_8021X
+	    || idx == IDX_WPA_PSK_PTKIP_GTKIP || idx == IDX_WPA_PSK_PTKIP_PCCMP_GTKIP)
+		return NM_802_11_AP_SEC_NONE;
+	else if (idx == IDX_RSN_PSK_PCCMP_GCCMP)
+		return NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_CCMP | NM_802_11_AP_SEC_KEY_MGMT_PSK;
+	else if (idx == IDX_RSN_PSK_PTKIP_PCCMP_GTKIP)
+		return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_PSK;
+	else if (idx == IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP)
+		return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_PSK;
+	else if (idx == IDX_WPA_RSN_PSK_PCCMP_GCCMP)
+		return NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_CCMP | NM_802_11_AP_SEC_KEY_MGMT_PSK;
+	else if (idx == IDX_RSN_8021X)
+		return NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_CCMP | NM_802_11_AP_SEC_KEY_MGMT_802_1X;
+	else
+		g_assert_not_reached ();
+}
+
+static guint32
+error_code_for_idx (guint32 idx, guint num)
+{
+	if (idx == IDX_OPEN)
+		return NM_CONNECTION_ERROR_INVALID_SETTING;
+	else if (idx == IDX_PRIV) {
+		if (num <= 3)
+			return NM_CONNECTION_ERROR_MISSING_PROPERTY;
+		else
+			return NM_CONNECTION_ERROR_INVALID_PROPERTY;
+	} else if (   idx == IDX_WPA_PSK_PTKIP_GTKIP || idx == IDX_WPA_PSK_PTKIP_PCCMP_GTKIP
+	           || idx == IDX_WPA_RSN_PSK_PCCMP_GCCMP || idx == IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP
+	           || idx == IDX_RSN_PSK_PTKIP_PCCMP_GTKIP || idx == IDX_RSN_PSK_PCCMP_GCCMP)
+		if (num == 4)
+			return NM_CONNECTION_ERROR_INVALID_PROPERTY;
+		else
+			return NM_CONNECTION_ERROR_INVALID_SETTING;
+	else
+		g_assert_not_reached ();
+}
+
+static void
+test_ap_wpa_eap_connection_1 (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+
+	test_ap_wpa_eap_connection_base (NULL, NULL,
+	                                 flags_for_idx (idx),
+	                                 wpa_flags_for_idx (idx),
+	                                 rsn_flags_for_idx (idx),
+	                                 FALSE,
+	                                 error_code_for_idx (idx, 1));
+}
+
+static void
+test_ap_wpa_eap_connection_2 (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+
+	test_ap_wpa_eap_connection_base (NULL, NULL,
+	                                 flags_for_idx (idx),
+	                                 wpa_flags_for_idx (idx),
+	                                 rsn_flags_for_idx (idx),
+	                                 TRUE,
+	                                 error_code_for_idx (idx, 2));
+}
+
+static void
+test_ap_wpa_eap_connection_3 (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+
+	test_ap_wpa_eap_connection_base (NULL, "open",
+	                                 flags_for_idx (idx),
+	                                 wpa_flags_for_idx (idx),
+	                                 rsn_flags_for_idx (idx),
+	                                 FALSE,
+	                                 error_code_for_idx (idx, 3));
+}
+
+static void
+test_ap_wpa_eap_connection_4 (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+
+	test_ap_wpa_eap_connection_base (NULL, "shared",
+	                                 flags_for_idx (idx),
+	                                 wpa_flags_for_idx (idx),
+	                                 rsn_flags_for_idx (idx),
+	                                 FALSE,
+	                                 error_code_for_idx (idx, 4));
+}
+
+static void
+test_ap_wpa_eap_connection_5 (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+
+	test_ap_wpa_eap_connection_base ("wpa-eap", "open",
+	                                 flags_for_idx (idx),
+	                                 wpa_flags_for_idx (idx),
+	                                 rsn_flags_for_idx (idx),
+	                                 FALSE,
+	                                 error_code_for_idx (idx, 5));
+}
+
+/*****************************************************************************/
+
+static void
+test_priv_ap_empty_connection (void)
+{
+	NMConnection *src, *expected;
+	const char *bssid = "01:02:03:04:05:06";
+	const char *ssid = "blahblah";
+	const KeyData exp_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that an empty connection is completed to a valid Static WEP
+	 * connection when completed with an AP with the Privacy bit set.
+	 */
+
+	src = nm_simple_connection_new ();
+	success = complete_connection (ssid, bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY,
+	                               NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE,
+	                               FALSE,
+	                               src, &error);
+
+	/* Static WEP connection expected */
+	expected = create_basic (ssid, NULL, NM_802_11_MODE_INFRA);
+	fill_wsec (expected, exp_wsec);
+	COMPARE (src, expected, success, error, 0, 0);
+
+	g_object_unref (src);
+	g_object_unref (expected);
+}
+
+/*****************************************************************************/
+
+static void
+test_priv_ap_leap_connection_1 (gconstpointer add_wifi)
+{
+	NMConnection *src, *expected;
+	const char *ssid = "blahblah";
+	const char *bssid = "01:02:03:04:05:06";
+	const char *leap_username = "Bill Smith";
+	const KeyData src_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0 },
+	    { NULL } };
+	const KeyData exp_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that an minimal LEAP connection specifying only key management and
+	 * the LEAP username is completed to a full LEAP connection when completed
+	 * with an AP with the Privacy bit set.
+	 */
+
+	src = nm_simple_connection_new ();
+	if (add_wifi)
+		fill_wifi_empty (src);
+	fill_wsec (src, src_wsec);
+	success = complete_connection (ssid, bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY,
+	                               NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE,
+	                               FALSE,
+	                               src, &error);
+	/* We expect success here; since LEAP APs just set the 'privacy' flag
+	 * there's no way to determine from the AP's beacon whether it's static WEP,
+	 * dynamic WEP, or LEAP.
+	 */
+	expected = create_basic (ssid, NULL, NM_802_11_MODE_INFRA);
+	fill_wsec (expected, exp_wsec);
+	COMPARE (src, expected, success, error, 0, 0);
+
+	g_object_unref (src);
+	g_object_unref (expected);
+}
+
+/*****************************************************************************/
+
+static void
+test_priv_ap_leap_connection_2 (void)
+{
+	NMConnection *src;
+	const char *bssid = "01:02:03:04:05:06";
+	const KeyData src_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that an minimal LEAP connection specifying only key management and
+	 * the LEAP auth alg is completed to a full LEAP connection when completed
+	 * with an AP with the Privacy bit set.
+	 */
+
+	src = nm_simple_connection_new ();
+	fill_wifi_empty (src);
+	fill_wsec (src, src_wsec);
+	success = complete_connection ("blahblah", bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY,
+	                               NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE,
+	                               FALSE,
+	                               src, &error);
+	/* We expect failure here, we need a LEAP username */
+	COMPARE (src, NULL, success, error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
+
+	g_object_unref (src);
+}
+
+/*****************************************************************************/
+
+static void
+test_priv_ap_dynamic_wep_1 (void)
+{
+	NMConnection *src, *expected;
+	const char *ssid = "blahblah";
+	const char *bssid = "01:02:03:04:05:06";
+	const KeyData src_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 },
+	    { NULL } };
+	const KeyData both_8021x[] = {
+	    { NM_SETTING_802_1X_EAP, "peap", 0 },
+	    { NM_SETTING_802_1X_IDENTITY, "Bill Smith", 0 },
+	    { NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", 0 },
+	    { NULL } };
+	const KeyData exp_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that an minimal Dynamic WEP connection specifying key management,
+	 * the auth algorithm, and valid 802.1x setting is completed to a valid
+	 * Dynamic WEP connection when completed with an AP with the Privacy bit set.
+	 */
+
+	src = nm_simple_connection_new ();
+	fill_wifi_empty (src);
+	fill_wsec (src, src_wsec);
+	fill_8021x (src, both_8021x);
+	success = complete_connection (ssid, bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY,
+	                               NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE,
+	                               FALSE,
+	                               src, &error);
+
+	/* We expect a completed Dynamic WEP connection */
+	expected = create_basic (ssid, NULL, NM_802_11_MODE_INFRA);
+	fill_wsec (expected, exp_wsec);
+	fill_8021x (expected, both_8021x);
+	COMPARE (src, expected, success, error, 0, 0);
+
+	g_object_unref (src);
+	g_object_unref (expected);
+}
+
+/*****************************************************************************/
+
+static void
+test_priv_ap_dynamic_wep_2 (void)
+{
+	NMConnection *src, *expected;
+	const char *ssid = "blahblah";
+	const char *bssid = "01:02:03:04:05:06";
+	const KeyData src_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 },
+	    { NULL } };
+	const KeyData both_8021x[] = {
+	    { NM_SETTING_802_1X_EAP, "peap", 0 },
+	    { NM_SETTING_802_1X_IDENTITY, "Bill Smith", 0 },
+	    { NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", 0 },
+	    { NULL } };
+	const KeyData exp_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that an minimal Dynamic WEP connection specifying only the auth
+	 * algorithm and a valid 802.1x setting is completed to a valid Dynamic
+	 * WEP connection when completed with an AP with the Privacy bit set.
+	 */
+
+	src = nm_simple_connection_new ();
+	fill_wifi_empty (src);
+	fill_wsec (src, src_wsec);
+	fill_8021x (src, both_8021x);
+	success = complete_connection (ssid, bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY,
+	                               NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE,
+	                               FALSE,
+	                               src, &error);
+
+	/* We expect a completed Dynamic WEP connection */
+	expected = create_basic (ssid, NULL, NM_802_11_MODE_INFRA);
+	fill_wsec (expected, exp_wsec);
+	fill_8021x (expected, both_8021x);
+	COMPARE (src, expected, success, error, 0, 0);
+
+	g_object_unref (src);
+	g_object_unref (expected);
+}
+
+/*****************************************************************************/
+
+static void
+test_priv_ap_dynamic_wep_3 (void)
+{
+	NMConnection *src;
+	const char *bssid = "01:02:03:04:05:06";
+	const KeyData src_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "shared", 0 },
+	    { NULL } };
+	const KeyData src_8021x[] = {
+	    { NM_SETTING_802_1X_EAP, "peap", 0 },
+	    { NM_SETTING_802_1X_IDENTITY, "Bill Smith", 0 },
+	    { NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Ensure that a basic connection specifying 'shared' auth and an 802.1x
+	 * setting is rejected, as 802.1x is incompatible with 'shared' auth.
+	 */
+
+	src = nm_simple_connection_new ();
+	fill_wifi_empty (src);
+	fill_wsec (src, src_wsec);
+	fill_8021x (src, src_8021x);
+	success = complete_connection ("blahblah", bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY,
+	                               NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE,
+	                               FALSE,
+	                               src, &error);
+	/* Expect failure; shared is not compatible with dynamic WEP */
+	COMPARE (src, NULL, success, error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+
+	g_object_unref (src);
+}
+
+/*****************************************************************************/
+
+static void
+test_priv_ap_wpa_psk_connection_1 (void)
+{
+	/* Test that a basic WPA-PSK connection is rejected when completion is
+	 * attempted with an AP with just the Privacy bit set.  Lack of WPA/RSN
+	 * flags means the AP provides Static/Dynamic WEP or LEAP, not WPA.
+	 */
+	test_ap_wpa_psk_connection_base (NULL, NULL,
+	                                 NM_802_11_AP_FLAGS_PRIVACY,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 FALSE,
+	                                 NM_CONNECTION_ERROR_INVALID_PROPERTY,
+	                                 NULL);
+}
+
+static void
+test_priv_ap_wpa_psk_connection_2 (void)
+{
+	/* Test that a basic WPA-PSK connection is rejected when completion is
+	 * attempted with an AP with just the Privacy bit set.  Lack of WPA/RSN
+	 * flags means the AP provides Static/Dynamic WEP or LEAP, not WPA.
+	 */
+	test_ap_wpa_psk_connection_base (NULL, NULL,
+	                                 NM_802_11_AP_FLAGS_PRIVACY,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 TRUE,
+	                                 NM_CONNECTION_ERROR_INVALID_PROPERTY,
+	                                 NULL);
+}
+
+static void
+test_priv_ap_wpa_psk_connection_3 (void)
+{
+	/* Test that a basic WPA-PSK connection specifying only the auth algorithm
+	 * is rejected when completion is attempted with an AP with just the Privacy
+	 * bit set.  Lack of WPA/RSN flags means the AP provides Static/Dynamic WEP
+	 * or LEAP, not WPA.
+	 */
+	test_ap_wpa_psk_connection_base (NULL, "open",
+	                                 NM_802_11_AP_FLAGS_PRIVACY,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 FALSE,
+	                                 NM_CONNECTION_ERROR_INVALID_PROPERTY,
+	                                 NULL);
+}
+
+static void
+test_priv_ap_wpa_psk_connection_4 (void)
+{
+	/* Test that a basic WPA-PSK connection specifying only the auth algorithm
+	 * is rejected when completion is attempted with an AP with just the Privacy
+	 * bit set.  Lack of WPA/RSN flags means the AP provides Static/Dynamic WEP
+	 * or LEAP, not WPA.  Second, 'shared' auth is incompatible with WPA.
+	 */
+	test_ap_wpa_psk_connection_base (NULL, "shared",
+	                                 NM_802_11_AP_FLAGS_PRIVACY,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 FALSE,
+	                                 NM_CONNECTION_ERROR_INVALID_PROPERTY,
+	                                 NULL);
+}
+
+static void
+test_priv_ap_wpa_psk_connection_5 (void)
+{
+	/* Test that a WPA-PSK connection specifying both the key management and
+	 * auth algorithm is rejected when completion is attempted with an AP with
+	 * just the Privacy bit set.  Lack of WPA/RSN flags means the AP provides
+	 * Static/Dynamic WEP or LEAP, not WPA.
+	 */
+	test_ap_wpa_psk_connection_base ("wpa-psk", "open",
+	                                 NM_802_11_AP_FLAGS_PRIVACY,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 NM_802_11_AP_SEC_NONE,
+	                                 FALSE,
+	                                 NM_CONNECTION_ERROR_INVALID_PROPERTY,
+	                                 NULL);
+}
+
+/*****************************************************************************/
+
+static void
+test_wpa_ap_empty_connection (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+	NMConnection *src, *expected;
+	const char *bssid = "01:02:03:04:05:06";
+	const char *ssid = "blahblah";
+	const KeyData exp_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that a basic WPA-PSK connection specifying just key management and
+	 * the auth algorithm is completed successfully when given an AP with WPA
+	 * or RSN flags.
+	 */
+
+	src = nm_simple_connection_new ();
+	success = complete_connection (ssid, bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY,
+	                               wpa_flags_for_idx (idx),
+	                               rsn_flags_for_idx (idx),
+	                               FALSE, src, &error);
+
+	/* WPA connection expected */
+	expected = create_basic (ssid, NULL, NM_802_11_MODE_INFRA);
+	fill_wsec (expected, exp_wsec);
+	COMPARE (src, expected, success, error, 0, 0);
+
+	g_object_unref (src);
+	g_object_unref (expected);
+}
+
+/*****************************************************************************/
+
+static void
+test_wpa_ap_leap_connection_1 (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+	NMConnection *src;
+	const char *ssid = "blahblah";
+	const char *bssid = "01:02:03:04:05:06";
+	const char *leap_username = "Bill Smith";
+	const KeyData src_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that completion of a LEAP connection with a WPA-enabled AP is
+	 * rejected since WPA APs (usually) do not support LEAP.
+	 */
+
+	src = nm_simple_connection_new ();
+	fill_wifi_empty (src);
+	fill_wsec (src, src_wsec);
+	success = complete_connection (ssid, bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY,
+	                               wpa_flags_for_idx (idx),
+	                               rsn_flags_for_idx (idx),
+	                               FALSE,
+	                               src, &error);
+	/* Expect failure here; WPA APs don't support old-school LEAP */
+	COMPARE (src, NULL, success, error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+
+	g_object_unref (src);
+}
+
+/*****************************************************************************/
+
+static void
+test_wpa_ap_leap_connection_2 (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+	NMConnection *src;
+	const char *bssid = "01:02:03:04:05:06";
+	const KeyData src_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that completion of a LEAP connection with a WPA-enabled AP is
+	 * rejected since WPA APs (usually) do not support LEAP.
+	 */
+
+	src = nm_simple_connection_new ();
+	fill_wifi_empty (src);
+	fill_wsec (src, src_wsec);
+	success = complete_connection ("blahblah", bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY,
+	                               wpa_flags_for_idx (idx),
+	                               rsn_flags_for_idx (idx),
+	                               FALSE,
+	                               src, &error);
+	/* We expect failure here, we need a LEAP username */
+	COMPARE (src, NULL, success, error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+
+	g_object_unref (src);
+}
+
+/*****************************************************************************/
+
+static void
+test_wpa_ap_dynamic_wep_connection (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+	NMConnection *src;
+	const char *bssid = "01:02:03:04:05:06";
+	const KeyData src_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 },
+	    { NULL } };
+	gboolean success;
+	GError *error = NULL;
+
+	/* Test that completion of a Dynamic WEP connection with a WPA-enabled AP is
+	 * rejected since WPA APs (usually) do not support Dynamic WEP.
+	 */
+
+	src = nm_simple_connection_new ();
+	fill_wifi_empty (src);
+	fill_wsec (src, src_wsec);
+	success = complete_connection ("blahblah", bssid,
+	                               NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY,
+	                               wpa_flags_for_idx (idx),
+	                               rsn_flags_for_idx (idx),
+	                               FALSE,
+	                               src, &error);
+	/* We expect failure here since Dynamic WEP is incompatible with WPA */
+	COMPARE (src, NULL, success, error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+
+	g_object_unref (src);
+}
+
+/*****************************************************************************/
+
+static void
+test_wpa_ap_wpa_psk_connection_1 (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+	NMConnection *expected;
+	const KeyData exp_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 },
+	    { NULL } };
+
+	expected = nm_simple_connection_new ();
+	fill_wsec (expected, exp_wsec);
+	test_ap_wpa_psk_connection_base (NULL, NULL,
+	                                 NM_802_11_AP_FLAGS_PRIVACY,
+	                                 wpa_flags_for_idx (idx),
+	                                 rsn_flags_for_idx (idx),
+	                                 FALSE,
+	                                 NM_CONNECTION_ERROR_INVALID_PROPERTY,
+	                                 expected);
+	g_object_unref (expected);
+}
+
+static void
+test_wpa_ap_wpa_psk_connection_2 (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+	NMConnection *expected;
+	const KeyData exp_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 },
+	    { NULL } };
+
+	expected = nm_simple_connection_new ();
+	fill_wsec (expected, exp_wsec);
+	test_ap_wpa_psk_connection_base (NULL, NULL,
+	                                 NM_802_11_AP_FLAGS_PRIVACY,
+	                                 wpa_flags_for_idx (idx),
+	                                 rsn_flags_for_idx (idx),
+	                                 TRUE,
+	                                 NM_CONNECTION_ERROR_INVALID_PROPERTY,
+	                                 expected);
+	g_object_unref (expected);
+}
+
+static void
+test_wpa_ap_wpa_psk_connection_3 (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+	NMConnection *expected;
+	const KeyData exp_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 },
+	    { NULL } };
+
+	expected = nm_simple_connection_new ();
+	fill_wsec (expected, exp_wsec);
+	test_ap_wpa_psk_connection_base (NULL, "open",
+	                                 NM_802_11_AP_FLAGS_PRIVACY,
+	                                 wpa_flags_for_idx (idx),
+	                                 rsn_flags_for_idx (idx),
+	                                 FALSE,
+	                                 NM_CONNECTION_ERROR_INVALID_PROPERTY,
+	                                 expected);
+	g_object_unref (expected);
+}
+
+static void
+test_wpa_ap_wpa_psk_connection_4 (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+	test_ap_wpa_psk_connection_base (NULL, "shared",
+	                                 NM_802_11_AP_FLAGS_PRIVACY,
+	                                 wpa_flags_for_idx (idx),
+	                                 rsn_flags_for_idx (idx),
+	                                 FALSE,
+	                                 NM_CONNECTION_ERROR_INVALID_PROPERTY,
+	                                 NULL);
+}
+
+static void
+test_wpa_ap_wpa_psk_connection_5 (gconstpointer data)
+{
+	guint idx = GPOINTER_TO_UINT (data);
+	NMConnection *expected;
+	const KeyData exp_wsec[] = {
+	    { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", 0 },
+	    { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 },
+	    { NULL } };
+
+	expected = nm_simple_connection_new ();
+	fill_wsec (expected, exp_wsec);
+	test_ap_wpa_psk_connection_base ("wpa-psk", "open",
+	                                 NM_802_11_AP_FLAGS_PRIVACY,
+	                                 wpa_flags_for_idx (idx),
+	                                 rsn_flags_for_idx (idx),
+	                                 FALSE,
+	                                 NM_CONNECTION_ERROR_INVALID_PROPERTY,
+	                                 expected);
+	g_object_unref (expected);
+}
+
+/*****************************************************************************/
+
+static void
+test_strength_dbm (void)
+{
+	/* boundary conditions first */
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (-1), ==, 100);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (-40), ==, 100);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (-30), ==, 100);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (-100), ==, 0);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (-200), ==, 0);
+
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (-81), ==, 32);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (-92), ==, 14);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (-74), ==, 44);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (-81), ==, 32);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (-66), ==, 57);
+}
+
+static void
+test_strength_percent (void)
+{
+	int i;
+
+	/* boundary conditions first */
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (0), ==, 0);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (100), ==, 100);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (110), ==, 100);
+
+	for (i = 0; i <= 100; i++)
+		g_assert_cmpint (nm_wifi_utils_level_to_quality (i), ==, i);
+}
+
+static void
+test_strength_wext (void)
+{
+	/* boundary conditions that we assume aren't WEXT first */
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (256), ==, 100);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (110), ==, 100);
+
+	/* boundary conditions that we assume are WEXT */
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (111), ==, 0);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (150), ==, 0);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (225), ==, 100);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (255), ==, 100);
+
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (157), ==, 2);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (200), ==, 74);
+	g_assert_cmpint (nm_wifi_utils_level_to_quality (215), ==, 99);
+}
+
+#define _assert_strength_in_range(x) \
+	({ \
+		guint32 _x = (x); \
+		g_assert_cmpint (_x, >=, 0); \
+		g_assert_cmpint (_x, <=, 100); \
+	})
+
+static void
+test_strength_all (void)
+{
+	int val;
+
+	for (val = -200; val < 300; val++)
+		_assert_strength_in_range (nm_wifi_utils_level_to_quality (val));
+	_assert_strength_in_range (nm_wifi_utils_level_to_quality (G_MININT));
+	_assert_strength_in_range (nm_wifi_utils_level_to_quality (G_MAXINT));
+	_assert_strength_in_range (nm_wifi_utils_level_to_quality (G_MININT32));
+	_assert_strength_in_range (nm_wifi_utils_level_to_quality (G_MAXINT32));
+	_assert_strength_in_range (nm_wifi_utils_level_to_quality (G_MININT16));
+	_assert_strength_in_range (nm_wifi_utils_level_to_quality (G_MAXINT16));
+}
+
+/*****************************************************************************/
+
+NMTST_DEFINE ();
+
+int
+main (int argc, char **argv)
+{
+	gsize i;
+
+	nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT");
+
+	g_test_add_func ("/wifi/lock_bssid",
+	                 test_lock_bssid);
+
+	/* Open AP tests; make sure that connections to be completed that have
+	 * various security-related settings already set cause the completion
+	 * to fail.
+	 */
+	g_test_add_func ("/wifi/open_ap/empty_connection",
+	                 test_open_ap_empty_connection);
+	g_test_add_data_func ("/wifi/open_ap/leap_connection/1",
+	                      (gconstpointer) TRUE,
+	                      test_open_ap_leap_connection_1);
+	g_test_add_data_func ("/wifi/open_ap/leap_connection/1_no_add_wifi",
+	                      (gconstpointer) FALSE,
+	                      test_open_ap_leap_connection_1);
+	g_test_add_func ("/wifi/open_ap/leap_connection/2",
+	                 test_open_ap_leap_connection_2);
+	g_test_add_data_func ("/wifi/open_ap/wep_connection_true",
+	                      (gconstpointer) TRUE,
+	                      test_open_ap_wep_connection);
+	g_test_add_data_func ("/wifi/open_ap/wep_connection_false",
+	                      (gconstpointer) FALSE,
+	                      test_open_ap_wep_connection);
+
+	g_test_add_func ("/wifi/open_ap/wpa_psk_connection/1",
+	                 test_open_ap_wpa_psk_connection_1);
+	g_test_add_func ("/wifi/open_ap/wpa_psk_connection/2",
+	                 test_open_ap_wpa_psk_connection_2);
+	g_test_add_func ("/wifi/open_ap/wpa_psk_connection/3",
+	                 test_open_ap_wpa_psk_connection_3);
+	g_test_add_func ("/wifi/open_ap/wpa_psk_connection/4",
+	                 test_open_ap_wpa_psk_connection_4);
+	g_test_add_func ("/wifi/open_ap/wpa_psk_connection/5",
+	                 test_open_ap_wpa_psk_connection_5);
+
+	g_test_add_data_func ("/wifi/open_ap/wpa_eap_connection/1",
+	                      (gconstpointer) IDX_OPEN,
+	                      test_ap_wpa_eap_connection_1);
+	g_test_add_data_func ("/wifi/open_ap/wpa_eap_connection/2",
+	                      (gconstpointer) IDX_OPEN,
+	                      test_ap_wpa_eap_connection_2);
+	g_test_add_data_func ("/wifi/open_ap/wpa_eap_connection/3",
+	                      (gconstpointer) IDX_OPEN,
+	                      test_ap_wpa_eap_connection_3);
+	g_test_add_data_func ("/wifi/open_ap/wpa_eap_connection/4",
+	                      (gconstpointer) IDX_OPEN,
+	                      test_ap_wpa_eap_connection_4);
+	g_test_add_data_func ("/wifi/open_ap/wpa_eap_connection/5",
+	                      (gconstpointer) IDX_OPEN,
+	                      test_ap_wpa_eap_connection_5);
+
+	/* WEP AP tests */
+	g_test_add_func ("/wifi/priv_ap/empty_connection",
+	                 test_priv_ap_empty_connection);
+	g_test_add_data_func ("/wifi/priv_ap/leap_connection/1",
+	                      (gconstpointer) FALSE,
+	                      test_priv_ap_leap_connection_1);
+	g_test_add_func ("/wifi/priv_ap/leap_connection/2",
+	                 test_priv_ap_leap_connection_2);
+
+	g_test_add_func ("/wifi/priv_ap/dynamic_wep/1",
+	                 test_priv_ap_dynamic_wep_1);
+	g_test_add_func ("/wifi/priv_ap/dynamic_wep/2",
+	                 test_priv_ap_dynamic_wep_2);
+	g_test_add_func ("/wifi/priv_ap/dynamic_wep/3",
+	                 test_priv_ap_dynamic_wep_3);
+
+	g_test_add_func ("/wifi/priv_ap/wpa_psk_connection/1",
+	                 test_priv_ap_wpa_psk_connection_1);
+	g_test_add_func ("/wifi/priv_ap/wpa_psk_connection/2",
+	                 test_priv_ap_wpa_psk_connection_2);
+	g_test_add_func ("/wifi/priv_ap/wpa_psk_connection/3",
+	                 test_priv_ap_wpa_psk_connection_3);
+	g_test_add_func ("/wifi/priv_ap/wpa_psk_connection/4",
+	                 test_priv_ap_wpa_psk_connection_4);
+	g_test_add_func ("/wifi/priv_ap/wpa_psk_connection/5",
+	                 test_priv_ap_wpa_psk_connection_5);
+
+	g_test_add_data_func ("/wifi/priv_ap/wpa_eap_connection/1",
+	                      (gconstpointer) IDX_PRIV,
+	                      test_ap_wpa_eap_connection_1);
+	g_test_add_data_func ("/wifi/priv_ap/wpa_eap_connection/2",
+	                      (gconstpointer) IDX_PRIV,
+	                      test_ap_wpa_eap_connection_2);
+	g_test_add_data_func ("/wifi/priv_ap/wpa_eap_connection/3",
+	                      (gconstpointer) IDX_PRIV,
+	                      test_ap_wpa_eap_connection_3);
+	g_test_add_data_func ("/wifi/priv_ap/wpa_eap_connection/4",
+	                      (gconstpointer) IDX_PRIV,
+	                      test_ap_wpa_eap_connection_4);
+	g_test_add_data_func ("/wifi/priv_ap/wpa_eap_connection/5",
+	                      (gconstpointer) IDX_PRIV,
+	                      test_ap_wpa_eap_connection_5);
+
+#define ADD_FUNC(func) do { \
+		char *name_idx = g_strdup_printf ("/wifi/wpa_psk/" G_STRINGIFY (func) "/%zd", i); \
+		g_test_add_data_func (name_idx, (gconstpointer) i, func); \
+		g_free (name_idx); \
+	} while (0)
+
+	/* WPA-PSK tests */
+	for (i = IDX_WPA_PSK_PTKIP_GTKIP; i <= IDX_WPA_RSN_PSK_PCCMP_GCCMP; i++) {
+		ADD_FUNC(test_wpa_ap_empty_connection);
+		ADD_FUNC(test_wpa_ap_leap_connection_1);
+		ADD_FUNC(test_wpa_ap_leap_connection_2);
+		ADD_FUNC(test_wpa_ap_dynamic_wep_connection);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_1);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_2);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_3);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_4);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_5);
+		ADD_FUNC(test_ap_wpa_eap_connection_1);
+		ADD_FUNC(test_ap_wpa_eap_connection_2);
+		ADD_FUNC(test_ap_wpa_eap_connection_3);
+		ADD_FUNC(test_ap_wpa_eap_connection_4);
+		ADD_FUNC(test_ap_wpa_eap_connection_5);
+	}
+
+#undef ADD_FUNC
+#define ADD_FUNC(func) do { \
+		char *name_idx = g_strdup_printf ("/wifi/rsn_psk/" G_STRINGIFY (func) "/%zd", i); \
+		g_test_add_data_func (name_idx, (gconstpointer) i, func); \
+		g_free (name_idx); \
+	} while (0)
+
+	/* RSN-PSK tests */
+	for (i = IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP; i <= IDX_RSN_PSK_PTKIP_PCCMP_GTKIP; i++) {
+		ADD_FUNC(test_wpa_ap_empty_connection);
+		ADD_FUNC(test_wpa_ap_leap_connection_1);
+		ADD_FUNC(test_wpa_ap_leap_connection_2);
+		ADD_FUNC(test_wpa_ap_dynamic_wep_connection);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_1);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_2);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_3);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_4);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_5);
+		ADD_FUNC(test_ap_wpa_eap_connection_1);
+		ADD_FUNC(test_ap_wpa_eap_connection_2);
+		ADD_FUNC(test_ap_wpa_eap_connection_3);
+		ADD_FUNC(test_ap_wpa_eap_connection_4);
+		ADD_FUNC(test_ap_wpa_eap_connection_5);
+	}
+
+#undef ADD_FUNC
+
+	/* Scanned signal strength conversion tests */
+	g_test_add_func ("/wifi/strength/dbm",
+	                 test_strength_dbm);
+	g_test_add_func ("/wifi/strength/percent",
+	                 test_strength_percent);
+	g_test_add_func ("/wifi/strength/wext",
+	                 test_strength_wext);
+	g_test_add_func ("/wifi/strength/all",
+	                 test_strength_all);
+
+	return g_test_run ();
+}