1 /* GLib testing framework examples and tests
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: David Zeuthen <davidz@redhat.com>
19  */
20 
21 #include <gio/gio.h>
22 #ifndef _MSC_VER
23 #include <unistd.h>
24 #endif
25 
26 #include "gdbus-tests.h"
27 
28 /* ---------------------------------------------------------------------------------------------------- */
29 
30 typedef struct
31 {
32   GMainLoop *loop;
33   gboolean   timed_out;
34 } PropertyNotifyData;
35 
36 static void
on_property_notify(GObject * object,GParamSpec * pspec,gpointer user_data)37 on_property_notify (GObject    *object,
38                     GParamSpec *pspec,
39                     gpointer    user_data)
40 {
41   PropertyNotifyData *data = user_data;
42   g_main_loop_quit (data->loop);
43 }
44 
45 static gboolean
on_property_notify_timeout(gpointer user_data)46 on_property_notify_timeout (gpointer user_data)
47 {
48   PropertyNotifyData *data = user_data;
49   data->timed_out = TRUE;
50   g_main_loop_quit (data->loop);
51   return G_SOURCE_CONTINUE;
52 }
53 
54 gboolean
_g_assert_property_notify_run(gpointer object,const gchar * property_name)55 _g_assert_property_notify_run (gpointer     object,
56                                const gchar *property_name)
57 {
58   gchar *s;
59   gulong handler_id;
60   guint timeout_id;
61   PropertyNotifyData data;
62 
63   data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
64   data.timed_out = FALSE;
65   s = g_strdup_printf ("notify::%s", property_name);
66   handler_id = g_signal_connect (object,
67                                  s,
68                                  G_CALLBACK (on_property_notify),
69                                  &data);
70   g_free (s);
71   timeout_id = g_timeout_add_seconds (30,
72                                       on_property_notify_timeout,
73                                       &data);
74   g_main_loop_run (data.loop);
75   g_signal_handler_disconnect (object, handler_id);
76   g_source_remove (timeout_id);
77   g_main_loop_unref (data.loop);
78 
79   return data.timed_out;
80 }
81 
82 static gboolean
_give_up(gpointer data)83 _give_up (gpointer data)
84 {
85   g_error ("%s", (const gchar *) data);
86   g_return_val_if_reached (G_SOURCE_CONTINUE);
87 }
88 
89 typedef struct
90 {
91   GMainContext *context;
92   gboolean name_appeared;
93   gboolean unwatch_complete;
94 } WatchData;
95 
96 static void
name_appeared_cb(GDBusConnection * connection,const gchar * name,const gchar * name_owner,gpointer user_data)97 name_appeared_cb (GDBusConnection *connection,
98                   const gchar     *name,
99                   const gchar     *name_owner,
100                   gpointer         user_data)
101 {
102   WatchData *data = user_data;
103 
104   g_assert (name_owner != NULL);
105   data->name_appeared = TRUE;
106   g_main_context_wakeup (data->context);
107 }
108 
109 static void
watch_free_cb(gpointer user_data)110 watch_free_cb (gpointer user_data)
111 {
112   WatchData *data = user_data;
113 
114   data->unwatch_complete = TRUE;
115   g_main_context_wakeup (data->context);
116 }
117 
118 void
ensure_gdbus_testserver_up(GDBusConnection * connection,GMainContext * context)119 ensure_gdbus_testserver_up (GDBusConnection *connection,
120                             GMainContext    *context)
121 {
122   GSource *timeout_source = NULL;
123   guint watch_id;
124   WatchData data = { context, FALSE, FALSE };
125 
126   g_main_context_push_thread_default (context);
127 
128   watch_id = g_bus_watch_name_on_connection (connection,
129                                              "com.example.TestService",
130                                              G_BUS_NAME_WATCHER_FLAGS_NONE,
131                                              name_appeared_cb,
132                                              NULL,
133                                              &data,
134                                              watch_free_cb);
135 
136   timeout_source = g_timeout_source_new_seconds (60);
137   g_source_set_callback (timeout_source, _give_up,
138                          "waited more than ~ 60s for gdbus-testserver to take its bus name",
139                          NULL);
140   g_source_attach (timeout_source, context);
141 
142   while (!data.name_appeared)
143     g_main_context_iteration (context, TRUE);
144 
145   g_bus_unwatch_name (watch_id);
146   watch_id = 0;
147 
148   while (!data.unwatch_complete)
149     g_main_context_iteration (context, TRUE);
150 
151   g_source_destroy (timeout_source);
152   g_source_unref (timeout_source);
153 
154   g_main_context_pop_thread_default (context);
155 }
156 
157 /* ---------------------------------------------------------------------------------------------------- */
158 
159 typedef struct
160 {
161   GMainLoop *loop;
162   gboolean   timed_out;
163 } SignalReceivedData;
164 
165 static void
on_signal_received(gpointer user_data)166 on_signal_received (gpointer user_data)
167 {
168   SignalReceivedData *data = user_data;
169   g_main_loop_quit (data->loop);
170 }
171 
172 static gboolean
on_signal_received_timeout(gpointer user_data)173 on_signal_received_timeout (gpointer user_data)
174 {
175   SignalReceivedData *data = user_data;
176   data->timed_out = TRUE;
177   g_main_loop_quit (data->loop);
178   return G_SOURCE_CONTINUE;
179 }
180 
181 gboolean
_g_assert_signal_received_run(gpointer object,const gchar * signal_name)182 _g_assert_signal_received_run (gpointer     object,
183                                const gchar *signal_name)
184 {
185   gulong handler_id;
186   guint timeout_id;
187   SignalReceivedData data;
188 
189   data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
190   data.timed_out = FALSE;
191   handler_id = g_signal_connect_swapped (object,
192                                          signal_name,
193                                          G_CALLBACK (on_signal_received),
194                                          &data);
195   timeout_id = g_timeout_add_seconds (30,
196                                       on_signal_received_timeout,
197                                       &data);
198   g_main_loop_run (data.loop);
199   g_signal_handler_disconnect (object, handler_id);
200   g_source_remove (timeout_id);
201   g_main_loop_unref (data.loop);
202 
203   return data.timed_out;
204 }
205 
206 /* ---------------------------------------------------------------------------------------------------- */
207 
208 GDBusConnection *
_g_bus_get_priv(GBusType bus_type,GCancellable * cancellable,GError ** error)209 _g_bus_get_priv (GBusType            bus_type,
210                  GCancellable       *cancellable,
211                  GError            **error)
212 {
213   gchar *address;
214   GDBusConnection *ret;
215 
216   ret = NULL;
217 
218   address = g_dbus_address_get_for_bus_sync (bus_type, cancellable, error);
219   if (address == NULL)
220     goto out;
221 
222   ret = g_dbus_connection_new_for_address_sync (address,
223                                                 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
224                                                 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
225                                                 NULL, /* GDBusAuthObserver */
226                                                 cancellable,
227                                                 error);
228   g_free (address);
229 
230  out:
231   return ret;
232 }
233 
234 /* ---------------------------------------------------------------------------------------------------- */
235