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