* bus/bus.c, bus/bus.h, bus/main.c, bus/test.c, dbus/dbus-sysdeps-unix.c, dbus/dbus...
[platform/upstream/dbus.git] / bus / test.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 client_watch_callback (DBusWatch     *watch,
41                        unsigned int   condition,
42                        void          *data)
43 {
44   /* FIXME this can be done in dbus-mainloop.c
45    * if the code in activation.c for the babysitter
46    * watch handler is fixed.
47    */
48  
49   return dbus_watch_handle (watch, condition);
50 }
51
52 static dbus_bool_t
53 add_client_watch (DBusWatch      *watch,
54                   void           *data)
55 {
56   DBusConnection *connection = data;
57   
58   return _dbus_loop_add_watch (client_loop,
59                                watch, client_watch_callback, connection,
60                                NULL);
61 }
62
63 static void
64 remove_client_watch (DBusWatch      *watch,
65                      void           *data)
66 {
67   DBusConnection *connection = data;
68   
69   _dbus_loop_remove_watch (client_loop,
70                            watch, client_watch_callback, connection);
71 }
72
73 static void
74 client_timeout_callback (DBusTimeout   *timeout,
75                          void          *data)
76 {
77   DBusConnection *connection = data;
78
79   dbus_connection_ref (connection);
80
81   /* can return FALSE on OOM but we just let it fire again later */
82   dbus_timeout_handle (timeout);
83
84   dbus_connection_unref (connection);
85 }
86
87 static dbus_bool_t
88 add_client_timeout (DBusTimeout    *timeout,
89                     void           *data)
90 {
91   DBusConnection *connection = data;
92   
93   return _dbus_loop_add_timeout (client_loop, timeout, client_timeout_callback, connection, NULL);
94 }
95
96 static void
97 remove_client_timeout (DBusTimeout    *timeout,
98                        void           *data)
99 {
100   DBusConnection *connection = data;
101   
102   _dbus_loop_remove_timeout (client_loop, timeout, client_timeout_callback, connection);
103 }
104
105 static DBusHandlerResult
106 client_disconnect_filter (DBusConnection     *connection,
107                           DBusMessage        *message,
108                           void               *user_data)
109 {
110   if (!dbus_message_is_signal (message,
111                                DBUS_INTERFACE_LOCAL,
112                                "Disconnected"))
113     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
114     
115   _dbus_verbose ("Removing client %p in disconnect handler\n",
116                  connection);
117   
118   _dbus_list_remove (&clients, connection);
119
120   dbus_connection_unref (connection);
121   
122   if (clients == NULL)
123     {
124       _dbus_loop_unref (client_loop);
125       client_loop = NULL;
126     }
127   
128   return DBUS_HANDLER_RESULT_HANDLED;
129 }
130
131 dbus_bool_t
132 bus_setup_debug_client (DBusConnection *connection)
133 {
134   dbus_bool_t retval;  
135
136   if (!dbus_connection_add_filter (connection,
137                                    client_disconnect_filter,
138                                    NULL, NULL))
139     return FALSE;
140
141   retval = FALSE;
142
143   if (client_loop == NULL)
144     {
145       client_loop = _dbus_loop_new ();
146       if (client_loop == NULL)
147         goto out;
148     }
149   
150   if (!dbus_connection_set_watch_functions (connection,
151                                             add_client_watch,
152                                             remove_client_watch,
153                                             NULL,
154                                             connection,
155                                             NULL))
156     goto out;
157       
158   if (!dbus_connection_set_timeout_functions (connection,
159                                               add_client_timeout,
160                                               remove_client_timeout,
161                                               NULL,
162                                               connection, NULL))
163     goto out;
164
165   if (!_dbus_list_append (&clients, connection))
166     goto out;
167   
168   retval = TRUE;
169   
170  out:
171   if (!retval)
172     {
173       dbus_connection_remove_filter (connection,
174                                      client_disconnect_filter,
175                                      NULL);
176       
177       dbus_connection_set_watch_functions (connection,
178                                            NULL, NULL, NULL, NULL, NULL);
179       dbus_connection_set_timeout_functions (connection,
180                                              NULL, NULL, NULL, NULL, NULL);
181
182       _dbus_list_remove_last (&clients, connection);
183
184       if (clients == NULL)
185         {
186           _dbus_loop_unref (client_loop);
187           client_loop = NULL;
188         }
189     }
190       
191   return retval;
192 }
193
194 void
195 bus_test_clients_foreach (BusConnectionForeachFunction  function,
196                           void                         *data)
197 {
198   DBusList *link;
199   
200   link = _dbus_list_get_first_link (&clients);
201   while (link != NULL)
202     {
203       DBusConnection *connection = link->data;
204       DBusList *next = _dbus_list_get_next_link (&clients, link);
205
206       if (!(* function) (connection, data))
207         break;
208       
209       link = next;
210     }
211 }
212
213 dbus_bool_t
214 bus_test_client_listed (DBusConnection *connection)
215 {
216   DBusList *link;
217   
218   link = _dbus_list_get_first_link (&clients);
219   while (link != NULL)
220     {
221       DBusConnection *c = link->data;
222       DBusList *next = _dbus_list_get_next_link (&clients, link);
223
224       if (c == connection)
225         return TRUE;
226       
227       link = next;
228     }
229
230   return FALSE;
231 }
232
233 void
234 bus_test_run_clients_loop (dbus_bool_t block_once)
235 {  
236   if (client_loop == NULL)
237     return;
238
239   _dbus_verbose ("---> Dispatching on \"client side\"\n");
240   
241   /* dispatch before we block so pending dispatches
242    * won't make our block return early
243    */
244   _dbus_loop_dispatch (client_loop);
245   
246   /* Do one blocking wait, since we're expecting data */
247   if (block_once)
248     {
249       _dbus_verbose ("---> blocking on \"client side\"\n");
250       _dbus_loop_iterate (client_loop, TRUE);
251     }
252
253   /* Then mop everything up */
254   while (_dbus_loop_iterate (client_loop, FALSE))
255     ;
256
257   _dbus_verbose ("---> Done dispatching on \"client side\"\n");
258 }
259
260 void
261 bus_test_run_bus_loop (BusContext *context,
262                        dbus_bool_t block_once)
263 {
264   _dbus_verbose ("---> Dispatching on \"server side\"\n");
265   
266   /* dispatch before we block so pending dispatches
267    * won't make our block return early
268    */
269   _dbus_loop_dispatch (bus_context_get_loop (context));
270   
271   /* Do one blocking wait, since we're expecting data */
272   if (block_once)
273     {
274       _dbus_verbose ("---> blocking on \"server side\"\n");
275       _dbus_loop_iterate (bus_context_get_loop (context), TRUE);
276     }
277
278   /* Then mop everything up */
279   while (_dbus_loop_iterate (bus_context_get_loop (context), FALSE))
280     ;
281
282   _dbus_verbose ("---> Done dispatching on \"server side\"\n");
283 }
284
285 void
286 bus_test_run_everything (BusContext *context)
287 {
288   while (_dbus_loop_iterate (bus_context_get_loop (context), FALSE) ||
289          (client_loop == NULL || _dbus_loop_iterate (client_loop, FALSE)))
290     ;
291 }
292
293 BusContext*
294 bus_context_new_test (const DBusString *test_data_dir,
295                       const char       *filename)
296 {
297   DBusError error;
298   DBusString config_file;
299   DBusString relative;
300   BusContext *context;
301   DBusPipe pipe;
302   
303   if (!_dbus_string_init (&config_file))
304     {
305       _dbus_warn ("No memory\n");
306       return NULL;
307     }
308
309   if (!_dbus_string_copy (test_data_dir, 0,
310                           &config_file, 0))
311     {
312       _dbus_warn ("No memory\n");
313       _dbus_string_free (&config_file);
314       return NULL;
315     }
316
317   _dbus_string_init_const (&relative, filename);
318
319   if (!_dbus_concat_dir_and_file (&config_file, &relative))
320     {
321       _dbus_warn ("No memory\n");
322       _dbus_string_free (&config_file);
323       return NULL;
324     }
325   
326   dbus_error_init (&error);
327   pipe = _dbus_pipe_init(-1);
328   context = bus_context_new (&config_file, FALSE, pipe, pipe, &error);
329   if (context == NULL)
330     {
331       _DBUS_ASSERT_ERROR_IS_SET (&error);
332       
333       _dbus_warn ("Failed to create debug bus context from configuration file %s: %s\n",
334                   filename, error.message);
335
336       dbus_error_free (&error);
337       
338       _dbus_string_free (&config_file);
339       
340       return NULL;
341     }
342
343   _dbus_string_free (&config_file);
344   
345   return context;
346 }
347
348 #endif