Home | History | Annotate | Download | only in test
      1 /* Regression test for passing unmodified messages between connections
      2  *
      3  * Author: Simon McVittie <simon.mcvittie (at) collabora.co.uk>
      4  * Copyright  2010-2011 Nokia Corporation
      5  *
      6  * Permission is hereby granted, free of charge, to any person
      7  * obtaining a copy of this software and associated documentation files
      8  * (the "Software"), to deal in the Software without restriction,
      9  * including without limitation the rights to use, copy, modify, merge,
     10  * publish, distribute, sublicense, and/or sell copies of the Software,
     11  * and to permit persons to whom the Software is furnished to do so,
     12  * subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be
     15  * included in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     21  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     22  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     24  * SOFTWARE.
     25  */
     26 
     27 #include <config.h>
     28 
     29 #include <glib.h>
     30 
     31 #include <dbus/dbus.h>
     32 #include <dbus/dbus-glib-lowlevel.h>
     33 
     34 /* This is basically a miniature dbus-daemon. We relay messages from the client
     35  * on the left to the client on the right.
     36  *
     37  * left      socket     left      dispatch     right    socket     right
     38  * client ===========>  server --------------> server ===========> client
     39  * conn                 conn                   conn                conn
     40  *
     41  * In the real dbus-daemon, the client connections would be out-of-process,
     42  * but here we're cheating and doing everything in-process.
     43  */
     44 
     45 typedef struct {
     46     DBusError e;
     47 
     48     DBusServer *server;
     49 
     50     DBusConnection *left_client_conn;
     51     DBusConnection *left_server_conn;
     52 
     53     DBusConnection *right_server_conn;
     54     DBusConnection *right_client_conn;
     55     /* queue of DBusMessage received by right_client_conn */
     56     GQueue messages;
     57 } Fixture;
     58 
     59 static void
     60 assert_no_error (const DBusError *e)
     61 {
     62   if (G_UNLIKELY (dbus_error_is_set (e)))
     63     g_error ("expected success but got error: %s: %s", e->name, e->message);
     64 }
     65 
     66 static DBusHandlerResult
     67 server_message_cb (DBusConnection *server_conn,
     68     DBusMessage *message,
     69     void *data)
     70 {
     71   Fixture *f = data;
     72 
     73   g_assert (server_conn == f->left_server_conn);
     74   g_assert (f->right_server_conn != NULL);
     75 
     76   dbus_connection_send (f->right_server_conn, message, NULL);
     77 
     78   return DBUS_HANDLER_RESULT_HANDLED;
     79 }
     80 
     81 static DBusHandlerResult
     82 right_client_message_cb (DBusConnection *client_conn,
     83     DBusMessage *message,
     84     void *data)
     85 {
     86   Fixture *f = data;
     87 
     88   g_assert (client_conn == f->right_client_conn);
     89   g_queue_push_tail (&f->messages, dbus_message_ref (message));
     90 
     91   return DBUS_HANDLER_RESULT_HANDLED;
     92 }
     93 
     94 static void
     95 new_conn_cb (DBusServer *server,
     96     DBusConnection *server_conn,
     97     void *data)
     98 {
     99   Fixture *f = data;
    100   dbus_bool_t have_mem;
    101 
    102   if (f->left_server_conn == NULL)
    103     {
    104       f->left_server_conn = dbus_connection_ref (server_conn);
    105 
    106       have_mem = dbus_connection_add_filter (server_conn,
    107           server_message_cb, f, NULL);
    108       g_assert (have_mem);
    109     }
    110   else
    111     {
    112       g_assert (f->right_server_conn == NULL);
    113       f->right_server_conn = dbus_connection_ref (server_conn);
    114     }
    115 
    116   dbus_connection_setup_with_g_main (server_conn, NULL);
    117 }
    118 
    119 static void
    120 setup (Fixture *f,
    121     gconstpointer data G_GNUC_UNUSED)
    122 {
    123   dbus_error_init (&f->e);
    124   g_queue_init (&f->messages);
    125 
    126   f->server = dbus_server_listen ("tcp:host=127.0.0.1", &f->e);
    127   assert_no_error (&f->e);
    128   g_assert (f->server != NULL);
    129 
    130   dbus_server_set_new_connection_function (f->server,
    131       new_conn_cb, f, NULL);
    132   dbus_server_setup_with_g_main (f->server, NULL);
    133 }
    134 
    135 static void
    136 test_connect (Fixture *f,
    137     gconstpointer data G_GNUC_UNUSED)
    138 {
    139   dbus_bool_t have_mem;
    140   char *address;
    141 
    142   g_assert (f->left_server_conn == NULL);
    143   g_assert (f->right_server_conn == NULL);
    144 
    145   address = dbus_server_get_address (f->server);
    146   g_assert (address != NULL);
    147 
    148   f->left_client_conn = dbus_connection_open_private (address, &f->e);
    149   assert_no_error (&f->e);
    150   g_assert (f->left_client_conn != NULL);
    151   dbus_connection_setup_with_g_main (f->left_client_conn, NULL);
    152 
    153   while (f->left_server_conn == NULL)
    154     {
    155       g_print (".");
    156       g_main_context_iteration (NULL, TRUE);
    157     }
    158 
    159   f->right_client_conn = dbus_connection_open_private (address, &f->e);
    160   assert_no_error (&f->e);
    161   g_assert (f->right_client_conn != NULL);
    162   dbus_connection_setup_with_g_main (f->right_client_conn, NULL);
    163 
    164   dbus_free (address);
    165 
    166   while (f->right_server_conn == NULL)
    167     {
    168       g_print (".");
    169       g_main_context_iteration (NULL, TRUE);
    170     }
    171 
    172   have_mem = dbus_connection_add_filter (f->right_client_conn,
    173       right_client_message_cb, f, NULL);
    174   g_assert (have_mem);
    175 }
    176 
    177 static dbus_uint32_t
    178 send_one (Fixture *f,
    179     const char *member)
    180 {
    181   dbus_bool_t have_mem;
    182   dbus_uint32_t serial;
    183   DBusMessage *outgoing;
    184 
    185   outgoing = dbus_message_new_signal ("/com/example/Hello",
    186       "com.example.Hello", member);
    187   g_assert (outgoing != NULL);
    188 
    189   have_mem = dbus_connection_send (f->left_client_conn, outgoing, &serial);
    190   g_assert (have_mem);
    191   g_assert (serial != 0);
    192 
    193   dbus_message_unref (outgoing);
    194   return serial;
    195 }
    196 
    197 static void
    198 test_relay (Fixture *f,
    199     gconstpointer data)
    200 {
    201   DBusMessage *incoming;
    202 
    203   test_connect (f, data);
    204 
    205   send_one (f, "First");
    206   send_one (f, "Second");
    207 
    208   while (g_queue_get_length (&f->messages) < 2)
    209     {
    210       g_print (".");
    211       g_main_context_iteration (NULL, TRUE);
    212     }
    213 
    214   g_assert_cmpuint (g_queue_get_length (&f->messages), ==, 2);
    215 
    216   incoming = g_queue_pop_head (&f->messages);
    217   g_assert_cmpstr (dbus_message_get_member (incoming), ==, "First");
    218   dbus_message_unref (incoming);
    219 
    220   incoming = g_queue_pop_head (&f->messages);
    221   g_assert_cmpstr (dbus_message_get_member (incoming), ==, "Second");
    222   dbus_message_unref (incoming);
    223 }
    224 
    225 /* An arbitrary number of messages */
    226 #define MANY 8192
    227 
    228 static void
    229 test_limit (Fixture *f,
    230     gconstpointer data)
    231 {
    232   DBusMessage *incoming;
    233   guint i;
    234 
    235   test_connect (f, data);
    236 
    237   /* This was an attempt to reproduce fd.o #34393. It didn't work. */
    238   g_test_bug ("34393");
    239   dbus_connection_set_max_received_size (f->left_server_conn, 1);
    240   g_main_context_iteration (NULL, TRUE);
    241 
    242   for (i = 0; i < MANY; i++)
    243     {
    244       gchar *buf = g_strdup_printf ("Message%u", i);
    245 
    246       send_one (f, buf);
    247       g_free (buf);
    248     }
    249 
    250   i = 0;
    251 
    252   while (i < MANY)
    253     {
    254       while (g_queue_is_empty (&f->messages))
    255         {
    256           g_main_context_iteration (NULL, TRUE);
    257         }
    258 
    259       while ((incoming = g_queue_pop_head (&f->messages)) != NULL)
    260         {
    261           i++;
    262           dbus_message_unref (incoming);
    263         }
    264     }
    265 }
    266 
    267 static void
    268 teardown (Fixture *f,
    269     gconstpointer data G_GNUC_UNUSED)
    270 {
    271   if (f->left_client_conn != NULL)
    272     {
    273       dbus_connection_close (f->left_client_conn);
    274       dbus_connection_unref (f->left_client_conn);
    275       f->left_client_conn = NULL;
    276     }
    277 
    278   if (f->right_client_conn != NULL)
    279     {
    280       dbus_connection_close (f->right_client_conn);
    281       dbus_connection_unref (f->right_client_conn);
    282       f->right_client_conn = NULL;
    283     }
    284 
    285   if (f->left_server_conn != NULL)
    286     {
    287       dbus_connection_close (f->left_server_conn);
    288       dbus_connection_unref (f->left_server_conn);
    289       f->left_server_conn = NULL;
    290     }
    291 
    292   if (f->right_server_conn != NULL)
    293     {
    294       dbus_connection_close (f->right_server_conn);
    295       dbus_connection_unref (f->right_server_conn);
    296       f->right_server_conn = NULL;
    297     }
    298 
    299   if (f->server != NULL)
    300     {
    301       dbus_server_disconnect (f->server);
    302       dbus_server_unref (f->server);
    303       f->server = NULL;
    304     }
    305 }
    306 
    307 int
    308 main (int argc,
    309     char **argv)
    310 {
    311   g_test_init (&argc, &argv, NULL);
    312   g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id=");
    313 
    314   g_test_add ("/connect", Fixture, NULL, setup,
    315       test_connect, teardown);
    316   g_test_add ("/relay", Fixture, NULL, setup,
    317       test_relay, teardown);
    318   g_test_add ("/limit", Fixture, NULL, setup,
    319       test_limit, teardown);
    320 
    321   return g_test_run ();
    322 }
    323