| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  | /* GLib testing framework examples and tests
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2010-05-10 08:07:28 -04:00
										 |  |  |  * Copyright (C) 2008-2010 Red Hat, Inc. | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							| 
									
										
										
										
											2017-05-27 17:19:21 +02:00
										 |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This library 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 | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General | 
					
						
							| 
									
										
										
										
											2014-01-23 12:58:29 +01:00
										 |  |  |  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Author: David Zeuthen <davidz@redhat.com> | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <gio/gio.h>
 | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "gdbus-tests.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* all tests rely on a shared mainloop */ | 
					
						
							|  |  |  | static GMainLoop *loop = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     const gchar *name; | 
					
						
							|  |  |  |     const gchar *bug; | 
					
						
							|  |  |  |     enum { | 
					
						
							|  |  |  |         EXPLICITLY_FALSE = FALSE, | 
					
						
							|  |  |  |         EXPLICITLY_TRUE = TRUE, | 
					
						
							|  |  |  |         IMPLICITLY_TRUE | 
					
						
							|  |  |  |     } exit_on_close; | 
					
						
							|  |  |  |     enum { | 
					
						
							|  |  |  |         LOCAL, | 
					
						
							|  |  |  |         REMOTE | 
					
						
							|  |  |  |     } who_closes; | 
					
						
							|  |  |  | } TestData; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const TestData cases[] = { | 
					
						
							|  |  |  |       { "default",  NULL,     IMPLICITLY_TRUE,  REMOTE }, | 
					
						
							|  |  |  |       { "true",     NULL,     EXPLICITLY_TRUE,  REMOTE }, | 
					
						
							|  |  |  |       { "false",    NULL,     EXPLICITLY_FALSE, REMOTE }, | 
					
						
							|  |  |  |       { "we-close", "662100", EXPLICITLY_TRUE,  LOCAL  }, | 
					
						
							|  |  |  |       { NULL } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  | static gboolean | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  | quit_later_cb (gpointer data G_GNUC_UNUSED) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  | { | 
					
						
							|  |  |  |   g_main_loop_quit (loop); | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  | closed_cb (GDBusConnection  *c G_GNUC_UNUSED, | 
					
						
							|  |  |  |            gboolean          remote_peer_vanished, | 
					
						
							|  |  |  |            GError           *error, | 
					
						
							|  |  |  |            gpointer          test_data) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  |   const TestData *td = test_data; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-03 18:32:53 +00:00
										 |  |  |   if (error == NULL) | 
					
						
							|  |  |  |     g_debug ("closed (%d, no error)", remote_peer_vanished); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     g_debug ("closed (%d, %s %d \"%s\")", remote_peer_vanished, | 
					
						
							|  |  |  |              g_quark_to_string (error->domain), error->code, error->message); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  |   g_assert_cmpint (remote_peer_vanished, ==, (td->who_closes == REMOTE)); | 
					
						
							|  |  |  |   g_assert_cmpint ((error == NULL), ==, (td->who_closes == LOCAL)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* we delay this so that if exit-on-close was going to happen, it will
 | 
					
						
							|  |  |  |    * win the race | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   g_timeout_add (50, quit_later_cb, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | close_async_cb (GObject *source G_GNUC_UNUSED, | 
					
						
							|  |  |  |                 GAsyncResult *res G_GNUC_UNUSED, | 
					
						
							|  |  |  |                 gpointer nil G_GNUC_UNUSED) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-11-03 18:32:53 +00:00
										 |  |  |   GError *error = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (g_dbus_connection_close_finish (G_DBUS_CONNECTION (source), | 
					
						
							|  |  |  |                                       res, | 
					
						
							|  |  |  |                                       &error)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_debug ("closed connection"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_warning ("failed to close connection: %s (%s #%d)", | 
					
						
							|  |  |  |                  error->message, g_quark_to_string (error->domain), | 
					
						
							|  |  |  |                  error->code); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-24 16:34:13 -05:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2012-11-24 15:58:36 -05:00
										 |  |  | test_exit_on_close_subprocess (gconstpointer test_data) | 
					
						
							| 
									
										
										
										
											2012-11-24 16:34:13 -05:00
										 |  |  | { | 
					
						
							|  |  |  |   const TestData *td = test_data; | 
					
						
							| 
									
										
										
										
											2012-11-24 15:58:36 -05:00
										 |  |  |   GDBusConnection *c; | 
					
						
							| 
									
										
										
										
											2012-12-19 15:20:37 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   loop = g_main_loop_new (NULL, FALSE); | 
					
						
							| 
									
										
										
										
											2012-11-24 16:34:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-24 15:58:36 -05:00
										 |  |  |   session_bus_up (); | 
					
						
							|  |  |  |   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_assert (c != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* the default is meant to be TRUE */ | 
					
						
							|  |  |  |   if (td->exit_on_close != IMPLICITLY_TRUE) | 
					
						
							|  |  |  |     g_dbus_connection_set_exit_on_close (c, td->exit_on_close); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_assert_cmpint (g_dbus_connection_get_exit_on_close (c), ==, | 
					
						
							|  |  |  |                    (td->exit_on_close != EXPLICITLY_FALSE)); | 
					
						
							|  |  |  |   g_assert (!g_dbus_connection_is_closed (c)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_timeout_add (50, quit_later_cb, NULL); | 
					
						
							|  |  |  |   g_main_loop_run (loop); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_signal_connect (c, "closed", G_CALLBACK (closed_cb), (gpointer) td); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (td->who_closes == LOCAL) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       GVariant *v; | 
					
						
							|  |  |  |       GError *error = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       v = g_dbus_connection_call_sync (c, "org.freedesktop.DBus", | 
					
						
							|  |  |  |                                        "/org/freedesktop/DBus", | 
					
						
							|  |  |  |                                        "org.freedesktop.DBus", | 
					
						
							|  |  |  |                                        "ListNames", | 
					
						
							|  |  |  |                                        NULL, | 
					
						
							|  |  |  |                                        G_VARIANT_TYPE ("(as)"), | 
					
						
							|  |  |  |                                        G_DBUS_CALL_FLAGS_NONE, | 
					
						
							|  |  |  |                                        -1, | 
					
						
							|  |  |  |                                        NULL, | 
					
						
							|  |  |  |                                        &error); | 
					
						
							|  |  |  |       g_assert_no_error (error); | 
					
						
							|  |  |  |       g_assert (v != NULL); | 
					
						
							|  |  |  |       g_variant_unref (v); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       g_dbus_connection_close (c, NULL, close_async_cb, NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       session_bus_stop (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_main_loop_run (loop); | 
					
						
							|  |  |  |   /* this is only reached when we turn off exit-on-close */ | 
					
						
							|  |  |  |   g_main_loop_unref (loop); | 
					
						
							|  |  |  |   g_object_unref (c); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   session_bus_down (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   exit (0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | test_exit_on_close (gconstpointer test_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const TestData *td = test_data; | 
					
						
							|  |  |  |   GTestSubprocessFlags flags; | 
					
						
							|  |  |  |   char *child_name; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 23:28:17 +02:00
										 |  |  |   g_test_dbus_unset (); | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-03 18:32:53 +00:00
										 |  |  |   if (g_test_verbose ()) | 
					
						
							| 
									
										
										
										
											2012-11-24 15:58:36 -05:00
										 |  |  |     flags = G_TEST_SUBPROCESS_INHERIT_STDOUT | G_TEST_SUBPROCESS_INHERIT_STDERR; | 
					
						
							| 
									
										
										
										
											2011-11-03 18:32:53 +00:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2012-11-24 15:58:36 -05:00
										 |  |  |     flags = 0; | 
					
						
							| 
									
										
										
										
											2011-11-03 18:32:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-24 15:58:36 -05:00
										 |  |  |   child_name = g_strdup_printf ("/gdbus/exit-on-close/%s/subprocess", td->name); | 
					
						
							|  |  |  |   g_test_trap_subprocess (child_name, 0, flags); | 
					
						
							|  |  |  |   g_free (child_name); | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (td->exit_on_close == EXPLICITLY_FALSE || | 
					
						
							|  |  |  |       td->who_closes == LOCAL) | 
					
						
							| 
									
										
										
										
											2015-08-06 17:00:16 -04:00
										 |  |  |     g_test_trap_assert_passed (); | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2015-08-06 17:00:16 -04:00
										 |  |  |     g_test_trap_assert_failed(); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | main (int   argc, | 
					
						
							|  |  |  |       char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  |   gint i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |   g_test_init (&argc, &argv, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  |   for (i = 0; cases[i].name != NULL; i++) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2012-11-24 15:58:36 -05:00
										 |  |  |       gchar *name; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-24 15:58:36 -05:00
										 |  |  |       name = g_strdup_printf ("/gdbus/exit-on-close/%s", cases[i].name); | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  |       g_test_add_data_func (name, &cases[i], test_exit_on_close); | 
					
						
							|  |  |  |       g_free (name); | 
					
						
							| 
									
										
										
										
											2012-11-24 15:58:36 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |       name = g_strdup_printf ("/gdbus/exit-on-close/%s/subprocess", cases[i].name); | 
					
						
							|  |  |  |       g_test_add_data_func (name, &cases[i], test_exit_on_close_subprocess); | 
					
						
							|  |  |  |       g_free (name); | 
					
						
							| 
									
										
										
										
											2011-10-18 16:18:21 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return g_test_run(); | 
					
						
							|  |  |  | } |