libnm: add a test for connection-deleted-while-being-created
authorDan Winship <danw@gnome.org>
Wed, 6 Aug 2014 22:07:42 +0000 (18:07 -0400)
committerDan Winship <danw@gnome.org>
Thu, 7 Aug 2014 19:43:43 +0000 (15:43 -0400)
Since NMRemoteSettings doesn't announce new connections until it has
fetched their properties, it's possible that a connection could get
deleted while we're waiting for it to be created. NMRemoteSettings has
code to deal with this, so add a test to make sure that it works.

libnm/tests/test-remote-settings-client.c
tools/test-networkmanager-service.py

index 3ba64a3..d0ba504 100644 (file)
@@ -34,6 +34,8 @@
 #include "nm-remote-settings.h"
 #include "common.h"
 
+#include "nm-test-utils.h"
+
 static NMTestServiceInfo *sinfo;
 static NMRemoteSettings *settings = NULL;
 DBusGConnection *bus = NULL;
@@ -47,8 +49,7 @@ add_cb (NMRemoteSettings *s,
         GError *error,
         gpointer user_data)
 {
-       if (error)
-               g_warning ("Add error: %s", error->message);
+       g_assert_no_error (error);
 
        *((gboolean *) user_data) = TRUE;
        remote = connection;
@@ -61,27 +62,11 @@ static void
 test_add_connection (void)
 {
        NMConnection *connection;
-       NMSettingConnection *s_con;
-       NMSettingWired *s_wired;
-       char *uuid;
        gboolean success;
        time_t start, now;
        gboolean done = FALSE;
 
-       connection = nm_connection_new ();
-
-       s_con = (NMSettingConnection *) nm_setting_connection_new ();
-       uuid = nm_utils_uuid_generate ();
-       g_object_set (G_OBJECT (s_con),
-                     NM_SETTING_CONNECTION_ID, TEST_CON_ID,
-                     NM_SETTING_CONNECTION_UUID, uuid,
-                     NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
-                     NULL);
-       g_free (uuid);
-       nm_connection_add_setting (connection, NM_SETTING (s_con));
-
-       s_wired = (NMSettingWired *) nm_setting_wired_new ();
-       nm_connection_add_setting (connection, NM_SETTING (s_wired));
+       connection = nmtst_create_minimal_connection (TEST_CON_ID, NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
 
        success = nm_remote_settings_add_connection (settings,
                                                     connection,
@@ -101,6 +86,7 @@ test_add_connection (void)
        g_assert (nm_connection_compare (connection,
                                         NM_CONNECTION (remote),
                                         NM_SETTING_COMPARE_FLAG_EXACT) == TRUE);
+       g_object_unref (connection);
 }
 
 /*******************************************************************/
@@ -345,6 +331,61 @@ test_remove_connection (void)
 
 /*******************************************************************/
 
+#define TEST_ADD_REMOVE_ID "add-remove-test-connection"
+
+static void
+add_remove_cb (NMRemoteSettings *s,
+               NMRemoteConnection *connection,
+               GError *error,
+               gpointer user_data)
+{
+       g_assert_error (error, NM_REMOTE_SETTINGS_ERROR, NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED);
+       g_assert (connection == NULL);
+
+       *((gboolean *) user_data) = TRUE;
+}
+
+static void
+test_add_remove_connection (void)
+{
+       GVariant *ret;
+       GError *error = NULL;
+       NMConnection *connection;
+       gboolean success;
+       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);
+       success = nm_remote_settings_add_connection (settings,
+                                                    connection,
+                                                    add_remove_cb,
+                                                    &done);
+       g_assert (success == TRUE);
+
+       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 GMainLoop *loop;
 
 static gboolean
@@ -462,6 +503,7 @@ main (int argc, char **argv)
        g_test_add_func ("/remote_settings/make_invisible", test_make_invisible);
        g_test_add_func ("/remote_settings/make_visible", test_make_visible);
        g_test_add_func ("/remote_settings/remove_connection", test_remove_connection);
+       g_test_add_func ("/remote_settings/add_remove_connection", test_add_remove_connection);
        g_test_add_func ("/remote_settings/nm_running", test_nm_running);
 
        ret = g_test_run ();
index 437381e..e04621f 100755 (executable)
@@ -747,6 +747,10 @@ class NetworkManager(ExportedObj):
                 return
         raise UnknownDeviceException("Device not found")
 
+    @dbus.service.method(IFACE_TEST, in_signature='', out_signature='')
+    def AutoRemoveNextConnection(self):
+        settings.auto_remove_next_connection()
+
 ###################################################################
 IFACE_CONNECTION = 'org.freedesktop.NetworkManager.Settings.Connection'
 
@@ -789,6 +793,7 @@ class Connection(dbus.service.Object):
 
     @dbus.service.method(dbus_interface=IFACE_CONNECTION, in_signature='', out_signature='')
     def Delete(self):
+        self.remove_from_connection()
         self.remove_func(self)
         self.Removed()
 
@@ -809,10 +814,14 @@ class Settings(dbus.service.Object):
         self.connections = {}
         self.bus = bus
         self.counter = 1
+        self.remove_next_connection = False
         self.props = {}
         self.props['Hostname'] = "foobar.baz"
         self.props['CanModify'] = True
 
+    def auto_remove_next_connection(self):
+        self.remove_next_connection = True;
+
     @dbus.service.method(dbus_interface=IFACE_SETTINGS, in_signature='', out_signature='ao')
     def ListConnections(self):
         return self.connections.keys()
@@ -824,6 +833,11 @@ class Settings(dbus.service.Object):
         self.connections[path] = Connection(self.bus, path, settings, self.delete_connection)
         self.NewConnection(path)
         self.PropertiesChanged({ 'connections': dbus.Array(self.connections.keys(), 'o') })
+
+        if self.remove_next_connection:
+            self.remove_next_connection = False
+            self.connections[path].Delete()
+
         return path
 
     def delete_connection(self, connection):
@@ -870,8 +884,11 @@ def main():
     random.seed()
 
     bus = dbus.SessionBus()
+
+    global manager, settings
     manager = NetworkManager(bus, "/org/freedesktop/NetworkManager")
     settings = Settings(bus, "/org/freedesktop/NetworkManager/Settings")
+
     if not bus.request_name("org.freedesktop.NetworkManager"):
         sys.exit(1)