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