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