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