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