about summary refs log tree commit diff
path: root/shared/nm-test-utils-impl.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-06-04 00:07:45 +0200
committerMichael Biebl <biebl@debian.org>2018-06-04 00:07:45 +0200
commit04bc9e1cd3544445d883ad29ea108c1645c8e7b7 (patch)
treed10c354b1b980ca8a7b9e48ec9019e8ed88bde2b /shared/nm-test-utils-impl.c
parentee9c73a923909e23a649407be77e25235d769e25 (diff)
New upstream version 1.11.4 upstream/1.11.4
Diffstat (limited to 'shared/nm-test-utils-impl.c')
-rw-r--r--shared/nm-test-utils-impl.c176
1 files changed, 136 insertions, 40 deletions
diff --git a/shared/nm-test-utils-impl.c b/shared/nm-test-utils-impl.c
index 3eb726d9..3add88c7 100644
--- a/shared/nm-test-utils-impl.c
+++ b/shared/nm-test-utils-impl.c
@@ -21,16 +21,15 @@
 #include "nm-default.h"
 
 #include <string.h>
+#include <sys/wait.h>
 
 #include "NetworkManager.h"
 #include "nm-dbus-compat.h"
 
-#if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
-#include "nm-dbus-glib-types.h"
-#endif
-
 #include "nm-test-libnm-utils.h"
 
+#define NMTSTC_NM_SERVICE NM_BUILD_SRCDIR"/tools/test-networkmanager-service.py"
+
 /*****************************************************************************/
 
 static gboolean
@@ -58,8 +57,7 @@ name_exists (GDBusConnection *c, const char *name)
 	return exists;
 }
 
-#if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
-
+#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB
 static DBusGProxy *
 _libdbus_create_proxy_test (DBusGConnection *bus)
 {
@@ -75,16 +73,62 @@ _libdbus_create_proxy_test (DBusGConnection *bus)
 
 	return proxy;
 }
-
 #endif
 
+typedef struct {
+	GMainLoop *mainloop;
+	GDBusConnection *bus;
+	int exit_code;
+	bool exited:1;
+	bool name_found:1;
+} ServiceInitWaitData;
+
+static gboolean
+_service_init_wait_probe_name (gpointer user_data)
+{
+	ServiceInitWaitData *data = user_data;
+
+	if (!name_exists (data->bus, "org.freedesktop.NetworkManager"))
+		return G_SOURCE_CONTINUE;
+
+	data->name_found = TRUE;
+	g_main_loop_quit (data->mainloop);
+	return G_SOURCE_REMOVE;
+}
+
+static void
+_service_init_wait_child_wait (GPid pid,
+                               gint status,
+                               gpointer user_data)
+{
+	ServiceInitWaitData *data = user_data;
+
+	data->exited = TRUE;
+	data->exit_code = status;
+	g_main_loop_quit (data->mainloop);
+}
+
+NMTstcServiceInfo *
+nmtstc_service_available (NMTstcServiceInfo *info)
+{
+	gs_free char *m = NULL;
+
+	if (info)
+		return info;
+
+	/* This happens, when test-networkmanager-service.py exits with 77 status
+	 * code. */
+	m = g_strdup_printf ("missing dependency for running NetworkManager stub service %s", NMTSTC_NM_SERVICE);
+	g_test_skip (m);
+	return NULL;
+}
+
 NMTstcServiceInfo *
 nmtstc_service_init (void)
 {
 	NMTstcServiceInfo *info;
-	const char *args[] = { TEST_NM_PYTHON, TEST_NM_SERVICE, NULL };
+	const char *args[] = { TEST_NM_PYTHON, NMTSTC_NM_SERVICE, NULL };
 	GError *error = NULL;
-	int i;
 
 	info = g_malloc0 (sizeof (*info));
 
@@ -96,18 +140,55 @@ nmtstc_service_init (void)
 	 * make sure the service exits if the test program crashes.
 	 */
 	g_spawn_async_with_pipes (NULL, (char **) args, NULL,
-	                          G_SPAWN_SEARCH_PATH,
+	                            G_SPAWN_SEARCH_PATH
+	                          | G_SPAWN_DO_NOT_REAP_CHILD,
 	                          NULL, NULL,
 	                          &info->pid, &info->keepalive_fd, NULL, NULL, &error);
 	g_assert_no_error (error);
 
-	/* Wait until the service is registered on the bus */
-	for (i = 1000; i > 0; i--) {
-		if (name_exists (info->bus, "org.freedesktop.NetworkManager"))
-			break;
-		g_usleep (G_USEC_PER_SEC / 50);
+	{
+		nm_auto_unref_gsource GSource *timeout_source = NULL;
+		nm_auto_unref_gsource GSource *child_source = NULL;
+		GMainContext *context = g_main_context_new ();
+		ServiceInitWaitData data = {
+			.bus = info->bus,
+			.mainloop = g_main_loop_new (context, FALSE),
+		};
+		gboolean had_timeout;
+
+		timeout_source = g_timeout_source_new (50);
+		g_source_set_callback (timeout_source, _service_init_wait_probe_name, &data, NULL);
+		g_source_attach (timeout_source, context);
+
+		child_source = g_child_watch_source_new (info->pid);
+		g_source_set_callback (child_source, (GSourceFunc)(void (*) (void)) _service_init_wait_child_wait, &data, NULL);
+		g_source_attach (child_source, context);
+
+		had_timeout = !nmtst_main_loop_run (data.mainloop, 3000);
+
+		g_source_destroy (timeout_source);
+		g_source_destroy (child_source);
+		g_main_loop_unref (data.mainloop);
+		g_main_context_unref (context);
+
+		if (had_timeout)
+			g_error ("test service %s did not start in time", NMTSTC_NM_SERVICE);
+		if (!data.name_found) {
+			g_assert (data.exited);
+			info->pid = NM_PID_T_INVAL;
+			nmtstc_service_cleanup (info);
+
+			if (   WIFEXITED (data.exit_code)
+			    && WEXITSTATUS (data.exit_code) == 77) {
+				/* If the stub service exited with status 77 it means that it decided
+				 * that it cannot conduct the tests and the test should be (gracefully)
+				 * skip. The likely reason for that, is that libnm is not available
+				 * via pygobject. */
+				return NULL;
+			}
+			g_error ("test service %s exited with error code %d", NMTSTC_NM_SERVICE, data.exit_code);
+		}
 	}
-	g_assert (i > 0);
 
 	/* Grab a proxy to our fake NM service to trigger tests */
 	info->proxy = g_dbus_proxy_new_sync (info->bus,
@@ -121,7 +202,7 @@ nmtstc_service_init (void)
 	                                     NULL, &error);
 	g_assert_no_error (error);
 
-#if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
+#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB
 	info->libdbus.bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
 	g_assert_no_error (error);
 	g_assert (info->libdbus.bus);
@@ -132,32 +213,50 @@ nmtstc_service_init (void)
 void
 nmtstc_service_cleanup (NMTstcServiceInfo *info)
 {
-	int i;
+	int ret;
+	gint64 t;
+	int status;
 
-	g_object_unref (info->proxy);
-	kill (info->pid, SIGTERM);
+	if (!info)
+		return;
 
-	/* Wait until the bus notices the service is gone */
-	for (i = 100; i > 0; i--) {
-		if (!name_exists (info->bus, "org.freedesktop.NetworkManager"))
-			break;
-		g_usleep (G_USEC_PER_SEC / 50);
-	}
-	g_assert (i > 0);
+	nm_close (nm_steal_fd (&info->keepalive_fd));
 
-	g_object_unref (info->bus);
-	nm_close (info->keepalive_fd);
+	g_clear_object (&info->proxy);
 
-#if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
+#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB
 	g_clear_pointer (&info->libdbus.bus, dbus_g_connection_unref);
 #endif
 
+	if (info->pid != NM_PID_T_INVAL) {
+		kill (info->pid, SIGTERM);
+
+		t = g_get_monotonic_time ();
+again_wait:
+		ret = waitpid (info->pid, &status, WNOHANG);
+		if (ret == 0) {
+			if (t + 2000000 < g_get_monotonic_time ()) {
+				kill (info->pid, SIGKILL);
+				g_error ("child process %lld did not exit within timeout", (long long) info->pid);
+			}
+			g_usleep (G_USEC_PER_SEC / 50);
+			goto again_wait;
+		}
+		if (ret == -1 && errno == EINTR)
+			goto again_wait;
+
+		g_assert (ret == info->pid);
+	}
+
+	g_assert (!name_exists (info->bus, "org.freedesktop.NetworkManager"));
+
+	g_clear_object (&info->bus);
+
 	memset (info, 0, sizeof (*info));
 	g_free (info);
 }
 
-#if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB)
-
+#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB)
 typedef struct {
 	GMainLoop *loop;
 	const char *ifname;
@@ -270,8 +369,7 @@ nmtstc_service_add_wired_device (NMTstcServiceInfo *sinfo, NMClient *client,
 {
 	return add_device_common (sinfo, client, "AddWiredDevice", ifname, hwaddr, subchannels);
 }
-
-#endif /* NM_NETWORKMANAGER_COMPILATION_LIB */
+#endif
 
 void
 nmtstc_service_add_connection (NMTstcServiceInfo *sinfo,
@@ -279,7 +377,7 @@ nmtstc_service_add_connection (NMTstcServiceInfo *sinfo,
                                gboolean verify_connection,
                                char **out_path)
 {
-#if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
+#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB
 	gs_unref_hashtable GHashTable *new_settings = NULL;
 	gboolean success;
 	gs_free_error GError *error = NULL;
@@ -353,7 +451,7 @@ nmtstc_service_update_connection (NMTstcServiceInfo *sinfo,
 		path = nm_connection_get_path (connection);
 	g_assert (path);
 
-#if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
+#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB
 	{
 		gs_unref_hashtable GHashTable *new_settings = NULL;
 		gboolean success;
@@ -414,8 +512,7 @@ nmtstc_service_update_connection_variant (NMTstcServiceInfo *sinfo,
 
 /*****************************************************************************/
 
-#if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
-
+#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_GLIB
 NMClient *
 nmtstc_nm_client_new (void)
 {
@@ -461,7 +558,6 @@ nmtstc_nm_remote_settings_new (void)
 
 	return settings;
 }
-
-#endif /* NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY */
+#endif
 
 /*****************************************************************************/