diff options
Diffstat (limited to 'libnm/tests/test-remote-settings-client.c')
| -rw-r--r-- | libnm/tests/test-remote-settings-client.c | 547 |
1 files changed, 547 insertions, 0 deletions
diff --git a/libnm/tests/test-remote-settings-client.c b/libnm/tests/test-remote-settings-client.c new file mode 100644 index 00000000..8f9dc27f --- /dev/null +++ b/libnm/tests/test-remote-settings-client.c @@ -0,0 +1,547 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; 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, 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 2010 - 2011 Red Hat, Inc. + * + */ + +#include "config.h" + +#include <glib.h> +#include <string.h> +#include <sys/types.h> +#include <signal.h> + +#include <NetworkManager.h> + +#include "common.h" + +#include "nm-test-utils.h" + +static NMTestServiceInfo *sinfo; +static NMClient *client = NULL; +GDBusConnection *bus = NULL; +NMRemoteConnection *remote = NULL; + +/*******************************************************************/ + +static void +add_cb (GObject *s, + GAsyncResult *result, + gpointer user_data) +{ + gboolean *done = user_data; + GError *error = NULL; + + remote = nm_client_add_connection_finish (client, result, &error); + g_assert_no_error (error); + + *done = TRUE; + g_object_add_weak_pointer (G_OBJECT (remote), (void **) &remote); + + /* nm_client_add_connection_finish() adds a ref to @remote, but we + * want the weak pointer to be cleared as soon as @client drops its own ref. + * So drop ours. + */ + g_object_unref (remote); +} + +#define TEST_CON_ID "blahblahblah" + +static void +test_add_connection (void) +{ + NMConnection *connection; + time_t start, now; + gboolean done = FALSE; + + connection = nmtst_create_minimal_connection (TEST_CON_ID, NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + + nm_client_add_connection_async (client, + connection, + TRUE, + NULL, + add_cb, + &done); + + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((done == FALSE) && (now - start < 5)); + g_assert (done == TRUE); + g_assert (remote != NULL); + + /* Make sure the connection is the same as what we added */ + g_assert (nm_connection_compare (connection, + NM_CONNECTION (remote), + NM_SETTING_COMPARE_FLAG_EXACT) == TRUE); + g_object_unref (connection); +} + +/*******************************************************************/ + +static void +set_visible_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + GVariant *ret; + + ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error); + g_assert_no_error (error); + g_variant_unref (ret); +} + +static void +visible_changed_cb (GObject *object, GParamSpec *pspec, gboolean *done) +{ + if (!nm_remote_connection_get_visible (NM_REMOTE_CONNECTION (object))) + *done = TRUE; +} + +static void +connection_removed_cb (NMClient *s, NMRemoteConnection *connection, gboolean *done) +{ + if (connection == remote) + *done = TRUE; +} + +static void +invis_has_settings_cb (NMSetting *setting, + const char *key, + const GValue *value, + GParamFlags flags, + gpointer user_data) +{ + *((gboolean *) user_data) = TRUE; +} + +static void +test_make_invisible (void) +{ + time_t start, now; + const GPtrArray *conns; + int i; + GDBusProxy *proxy; + gboolean visible_changed = FALSE, connection_removed = FALSE; + gboolean has_settings = FALSE; + char *path; + + g_assert (remote != NULL); + + /* Listen for the remove event when the connection becomes invisible */ + g_signal_connect (remote, "notify::" NM_REMOTE_CONNECTION_VISIBLE, G_CALLBACK (visible_changed_cb), &visible_changed); + g_signal_connect (client, "connection-removed", G_CALLBACK (connection_removed_cb), &connection_removed); + + path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote))); + proxy = g_dbus_proxy_new_sync (bus, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + NM_DBUS_SERVICE, + path, + NM_DBUS_INTERFACE_SETTINGS_CONNECTION, + NULL, + NULL); + g_assert (proxy != NULL); + + /* Bypass the NMClient object so we can test it independently */ + g_dbus_proxy_call (proxy, + "SetVisible", + g_variant_new ("(b)", FALSE), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + set_visible_cb, NULL); + + /* Wait for the connection to be removed */ + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((!visible_changed || !connection_removed) && (now - start < 5)); + g_assert (visible_changed == TRUE); + g_assert (connection_removed == TRUE); + + g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (visible_changed_cb), &visible_changed); + g_signal_handlers_disconnect_by_func (client, G_CALLBACK (connection_removed_cb), &connection_removed); + + /* Ensure NMClient no longer has the connection */ + conns = nm_client_get_connections (client); + for (i = 0; i < conns->len; i++) { + NMConnection *candidate = NM_CONNECTION (conns->pdata[i]); + + g_assert ((gpointer) remote != (gpointer) candidate); + g_assert (strcmp (path, nm_connection_get_path (candidate)) != 0); + } + + /* And ensure the invisible connection no longer has any settings */ + g_assert (remote); + nm_connection_for_each_setting_value (NM_CONNECTION (remote), + invis_has_settings_cb, + &has_settings); + g_assert (has_settings == FALSE); + + g_free (path); + g_object_unref (proxy); +} + +/*******************************************************************/ + +static void +vis_new_connection_cb (NMClient *foo, + NMRemoteConnection *connection, + NMRemoteConnection **new) +{ + *new = connection; +} + +static void +test_make_visible (void) +{ + time_t start, now; + const GPtrArray *conns; + int i; + GDBusProxy *proxy; + gboolean found = FALSE; + char *path; + NMRemoteConnection *new = NULL; + + g_assert (remote != NULL); + + /* Wait for the new-connection signal when the connection is visible again */ + g_signal_connect (client, NM_CLIENT_CONNECTION_ADDED, + G_CALLBACK (vis_new_connection_cb), &new); + + path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote))); + proxy = g_dbus_proxy_new_sync (bus, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + NM_DBUS_SERVICE, + path, + NM_DBUS_INTERFACE_SETTINGS_CONNECTION, + NULL, + NULL); + g_assert (proxy != NULL); + + /* Bypass the NMClient object so we can test it independently */ + g_dbus_proxy_call (proxy, + "SetVisible", + g_variant_new ("(b)", TRUE), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + set_visible_cb, NULL); + + /* Wait for the settings service to announce the connection again */ + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((new == NULL) && (now - start < 5)); + + /* Ensure the new connection is the same as the one we made visible again */ + g_assert (new); + g_assert (new == remote); + + g_signal_handlers_disconnect_by_func (client, G_CALLBACK (vis_new_connection_cb), &new); + + /* Ensure NMClient has the connection */ + conns = nm_client_get_connections (client); + for (i = 0; i < conns->len; i++) { + NMConnection *candidate = NM_CONNECTION (conns->pdata[i]); + + if ((gpointer) remote == (gpointer) candidate) { + g_assert_cmpstr (path, ==, nm_connection_get_path (candidate)); + g_assert_cmpstr (TEST_CON_ID, ==, nm_connection_get_id (candidate)); + found = TRUE; + break; + } + } + g_assert (found == TRUE); + + g_free (path); + g_object_unref (proxy); +} + +/*******************************************************************/ + +static void +deleted_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + GVariant *ret; + + ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error); + g_assert_no_error (error); + g_variant_unref (ret); +} + +static void +removed_cb (NMClient *s, NMRemoteConnection *connection, gboolean *done) +{ + if (connection == remote) + *done = TRUE; +} + +static void +test_remove_connection (void) +{ + NMRemoteConnection *connection; + time_t start, now; + const GPtrArray *conns; + int i; + GDBusProxy *proxy; + gboolean done = FALSE; + char *path; + + /* Find a connection to delete */ + conns = nm_client_get_connections (client); + g_assert_cmpint (conns->len, >, 0); + + connection = NM_REMOTE_CONNECTION (conns->pdata[0]); + g_assert (connection); + g_assert (remote == connection); + path = g_strdup (nm_connection_get_path (NM_CONNECTION (connection))); + g_signal_connect (client, "connection-removed", G_CALLBACK (removed_cb), &done); + + proxy = g_dbus_proxy_new_sync (bus, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + NM_DBUS_SERVICE, + path, + NM_DBUS_INTERFACE_SETTINGS_CONNECTION, + NULL, + NULL); + g_assert (proxy != NULL); + + /* Bypass the NMClient object so we can test it independently */ + g_dbus_proxy_call (proxy, + "Delete", + NULL, + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + deleted_cb, NULL); + + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((done == FALSE) && (now - start < 5)); + g_assert (done == TRUE); + + g_assert (!remote); + + /* Ensure NMClient no longer has the connection */ + conns = nm_client_get_connections (client); + for (i = 0; i < conns->len; i++) { + NMConnection *candidate = NM_CONNECTION (conns->pdata[i]); + + g_assert ((gpointer) connection != (gpointer) candidate); + g_assert_cmpstr (path, ==, nm_connection_get_path (candidate)); + } + + g_free (path); + g_object_unref (proxy); +} + +/*******************************************************************/ + +#define TEST_ADD_REMOVE_ID "add-remove-test-connection" + +static void +add_remove_cb (GObject *s, + GAsyncResult *result, + gpointer user_data) +{ + NMRemoteConnection *connection; + gboolean *done = user_data; + GError *error = NULL; + + connection = nm_client_add_connection_finish (client, result, &error); + g_assert_error (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_OBJECT_CREATION_FAILED); + g_assert (connection == NULL); + + *done = TRUE; +} + +static void +test_add_remove_connection (void) +{ + GVariant *ret; + GError *error = NULL; + NMConnection *connection; + time_t start, now; + gboolean done = FALSE; + + /* This will cause the test server to immediately delete the connection + * after creating it. + */ + ret = g_dbus_proxy_call_sync (sinfo->proxy, + "AutoRemoveNextConnection", + NULL, + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + &error); + g_assert_no_error (error); + g_variant_unref (ret); + + connection = nmtst_create_minimal_connection (TEST_ADD_REMOVE_ID, NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + nm_client_add_connection_async (client, + connection, + TRUE, + NULL, + add_remove_cb, + &done); + + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((done == FALSE) && (now - start < 5)); + g_assert (done == TRUE); + + g_object_unref (connection); +} + +/*******************************************************************/ + +static void +add_bad_cb (GObject *s, + GAsyncResult *result, + gpointer user_data) +{ + gboolean *done = user_data; + GError *error = NULL; + + remote = nm_client_add_connection_finish (client, result, &error); + g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + + *done = TRUE; +} + +static void +test_add_bad_connection (void) +{ + NMConnection *connection; + time_t start, now; + gboolean done = FALSE; + + /* The test daemon doesn't support bond connections */ + connection = nmtst_create_minimal_connection ("bad connection test", NULL, NM_SETTING_BOND_SETTING_NAME, NULL); + + nm_client_add_connection_async (client, + connection, + TRUE, + NULL, + add_bad_cb, + &done); + g_object_unref (connection); + + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((done == FALSE) && (now - start < 5)); + g_assert (done == TRUE); + g_assert (remote == NULL); +} + +/*******************************************************************/ + +static void +save_hostname_cb (GObject *s, + GAsyncResult *result, + gpointer user_data) +{ + gboolean *done = user_data; + GError *error = NULL; + + nm_client_save_hostname_finish (client, result, &error); + g_assert_no_error (error); + + *done = TRUE; +} + +static void +test_save_hostname (void) +{ + time_t start, now; + gboolean done = FALSE; + GError *error = NULL; + + /* test-networkmanager-service.py requires the hostname to contain a '.' */ + nm_client_save_hostname (client, "foo", NULL, &error); + g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_HOSTNAME); + g_clear_error (&error); + + nm_client_save_hostname_async (client, "example.com", NULL, save_hostname_cb, &done); + + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((done == FALSE) && (now - start < 5)); + g_assert (done == TRUE); + g_assert (remote == NULL); +} + +/*******************************************************************/ + +int +main (int argc, char **argv) +{ + int ret; + GError *error = NULL; + + g_setenv ("LIBNM_USE_SESSION_BUS", "1", TRUE); + +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + g_assert_no_error (error); + + sinfo = nm_test_service_init (); + + client = nm_client_new (NULL, &error); + g_assert_no_error (error); + g_assert (client != NULL); + + /* FIXME: these tests assume that they get run in order, but g_test_run() + * does not actually guarantee that! + */ + g_test_add_func ("/client/add_connection", test_add_connection); + g_test_add_func ("/client/make_invisible", test_make_invisible); + g_test_add_func ("/client/make_visible", test_make_visible); + g_test_add_func ("/client/remove_connection", test_remove_connection); + g_test_add_func ("/client/add_remove_connection", test_add_remove_connection); + g_test_add_func ("/client/add_bad_connection", test_add_bad_connection); + g_test_add_func ("/client/save_hostname", test_save_hostname); + + ret = g_test_run (); + + nm_test_service_cleanup (sinfo); + g_object_unref (client); + g_object_unref (bus); + + return ret; +} + |