Home | History | Annotate | Download | only in bus
      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
     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
     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
     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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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*
    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