Merge branch 'dbus-1.4'
[platform/upstream/dbus.git] / bus / test.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* test.c  unit test routines
3  *
4  * Copyright (C) 2003 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #include <config.h>
25
26 #ifdef DBUS_BUILD_TESTS
27 #include "test.h"
28 #include <dbus/dbus-internals.h>
29 #include <dbus/dbus-list.h>
30 #include <dbus/dbus-sysdeps.h>
31
32 /* The "debug client" watch/timeout handlers don't dispatch messages,
33  * as we manually pull them in order to verify them. This is why they
34  * are different from the real handlers in connection.c
35  */
36 static DBusList *clients = NULL;
37 static DBusLoop *client_loop = NULL;
38
39 static dbus_bool_t
40 add_client_watch (DBusWatch      *watch,
41                   void           *data)
42 {
43   DBusConnection *connection = data;
44
45   return _dbus_loop_add_watch (client_loop, watch);
46 }
47
48 static void
49 remove_client_watch (DBusWatch      *watch,
50                      void           *data)
51 {
52   DBusConnection *connection = data;
53
54   _dbus_loop_remove_watch (client_loop, watch);
55 }
56
57 static dbus_bool_t
58 add_client_timeout (DBusTimeout    *timeout,
59                     void           *data)
60 {
61   DBusConnection *connection = data;
62
63   return _dbus_loop_add_timeout (client_loop, timeout);
64 }
65
66 static void
67 remove_client_timeout (DBusTimeout    *timeout,
68                        void           *data)
69 {
70   DBusConnection *connection = data;
71
72   _dbus_loop_remove_timeout (client_loop, timeout);
73 }
74
75 static DBusHandlerResult
76 client_disconnect_filter (DBusConnection     *connection,
77                           DBusMessage        *message,
78                           void               *user_data)
79 {
80   if (!dbus_message_is_signal (message,
81                                DBUS_INTERFACE_LOCAL,
82                                "Disconnected"))
83     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
84
85   _dbus_verbose ("Removing client %p in disconnect handler\n",
86                  connection);
87
88   _dbus_list_remove (&clients, connection);
89
90   dbus_connection_unref (connection);
91
92   if (clients == NULL)
93     {
94       _dbus_loop_unref (client_loop);
95       client_loop = NULL;
96     }
97
98   return DBUS_HANDLER_RESULT_HANDLED;
99 }
100
101 dbus_bool_t
102 bus_setup_debug_client (DBusConnection *connection)
103 {
104   dbus_bool_t retval;
105
106   if (!dbus_connection_add_filter (connection,
107                                    client_disconnect_filter,
108                                    NULL, NULL))
109     return FALSE;
110
111   retval = FALSE;
112
113   if (client_loop == NULL)
114     {
115       client_loop = _dbus_loop_new ();
116       if (client_loop == NULL)
117         goto out;
118     }
119
120   if (!dbus_connection_set_watch_functions (connection,
121                                             add_client_watch,
122                                             remove_client_watch,
123                                             NULL,
124                                             connection,
125                                             NULL))
126     goto out;
127
128   if (!dbus_connection_set_timeout_functions (connection,
129                                               add_client_timeout,
130                                               remove_client_timeout,
131                                               NULL,
132                                               connection, NULL))
133     goto out;
134
135   if (!_dbus_list_append (&clients, connection))
136     goto out;
137
138   retval = TRUE;
139
140  out:
141   if (!retval)
142     {
143       dbus_connection_remove_filter (connection,
144                                      client_disconnect_filter,
145                                      NULL);
146
147       dbus_connection_set_watch_functions (connection,
148                                            NULL, NULL, NULL, NULL, NULL);
149       dbus_connection_set_timeout_functions (connection,
150                                              NULL, NULL, NULL, NULL, NULL);
151
152       _dbus_list_remove_last (&clients, connection);
153
154       if (clients == NULL)
155         {
156           _dbus_loop_unref (client_loop);
157           client_loop = NULL;
158         }
159     }
160
161   return retval;
162 }
163
164 void
165 bus_test_clients_foreach (BusConnectionForeachFunction  function,
166                           void                         *data)
167 {
168   DBusList *link;
169
170   link = _dbus_list_get_first_link (&clients);
171   while (link != NULL)
172     {
173       DBusConnection *connection = link->data;
174       DBusList *next = _dbus_list_get_next_link (&clients, link);
175
176       if (!(* function) (connection, data))
177         break;
178
179       link = next;
180     }
181 }
182
183 dbus_bool_t
184 bus_test_client_listed (DBusConnection *connection)
185 {
186   DBusList *link;
187
188   link = _dbus_list_get_first_link (&clients);
189   while (link != NULL)
190     {
191       DBusConnection *c = link->data;
192       DBusList *next = _dbus_list_get_next_link (&clients, link);
193
194       if (c == connection)
195         return TRUE;
196
197       link = next;
198     }
199
200   return FALSE;
201 }
202
203 void
204 bus_test_run_clients_loop (dbus_bool_t block_once)
205 {
206   if (client_loop == NULL)
207     return;
208
209   _dbus_verbose ("---> Dispatching on \"client side\"\n");
210
211   /* dispatch before we block so pending dispatches
212    * won't make our block return early
213    */
214   _dbus_loop_dispatch (client_loop);
215
216   /* Do one blocking wait, since we're expecting data */
217   if (block_once)
218     {
219       _dbus_verbose ("---> blocking on \"client side\"\n");
220       _dbus_loop_iterate (client_loop, TRUE);
221     }
222
223   /* Then mop everything up */
224   while (_dbus_loop_iterate (client_loop, FALSE))
225     ;
226
227   _dbus_verbose ("---> Done dispatching on \"client side\"\n");
228 }
229
230 void
231 bus_test_run_bus_loop (BusContext *context,
232                        dbus_bool_t block_once)
233 {
234   _dbus_verbose ("---> Dispatching on \"server side\"\n");
235
236   /* dispatch before we block so pending dispatches
237    * won't make our block return early
238    */
239   _dbus_loop_dispatch (bus_context_get_loop (context));
240
241   /* Do one blocking wait, since we're expecting data */
242   if (block_once)
243     {
244       _dbus_verbose ("---> blocking on \"server side\"\n");
245       _dbus_loop_iterate (bus_context_get_loop (context), TRUE);
246     }
247
248   /* Then mop everything up */
249   while (_dbus_loop_iterate (bus_context_get_loop (context), FALSE))
250     ;
251
252   _dbus_verbose ("---> Done dispatching on \"server side\"\n");
253 }
254
255 void
256 bus_test_run_everything (BusContext *context)
257 {
258   while (_dbus_loop_iterate (bus_context_get_loop (context), FALSE) ||
259          (client_loop == NULL || _dbus_loop_iterate (client_loop, FALSE)))
260     ;
261 }
262
263 BusContext*
264 bus_context_new_test (const DBusString *test_data_dir,
265                       const char       *filename)
266 {
267   DBusError error;
268   DBusString config_file;
269   DBusString relative;
270   BusContext *context;
271
272   if (!_dbus_string_init (&config_file))
273     {
274       _dbus_warn ("No memory\n");
275       return NULL;
276     }
277
278   if (!_dbus_string_copy (test_data_dir, 0,
279                           &config_file, 0))
280     {
281       _dbus_warn ("No memory\n");
282       _dbus_string_free (&config_file);
283       return NULL;
284     }
285
286   _dbus_string_init_const (&relative, filename);
287
288   if (!_dbus_concat_dir_and_file (&config_file, &relative))
289     {
290       _dbus_warn ("No memory\n");
291       _dbus_string_free (&config_file);
292       return NULL;
293     }
294
295   dbus_error_init (&error);
296   context = bus_context_new (&config_file, FALSE, NULL, NULL, NULL, FALSE, &error);
297   if (context == NULL)
298     {
299       _DBUS_ASSERT_ERROR_IS_SET (&error);
300
301       _dbus_warn ("Failed to create debug bus context from configuration file %s: %s\n",
302                   filename, error.message);
303
304       dbus_error_free (&error);
305
306       _dbus_string_free (&config_file);
307
308       return NULL;
309     }
310
311   _dbus_string_free (&config_file);
312
313   return context;
314 }
315
316 #endif