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