Home | History | Annotate | Download | only in name-test
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <unistd.h>
      4 #include <string.h>
      5 #include <dbus/dbus.h>
      6 #include <dbus/dbus-connection-internal.h>
      7 
      8 #define REMOVE_CONNECTION 0
      9 #define ADD_CONNECTION 1
     10 #define ALLOW_REPLACEMENT DBUS_NAME_FLAG_ALLOW_REPLACEMENT
     11 #define REPLACE_EXISTING DBUS_NAME_FLAG_REPLACE_EXISTING
     12 #define DO_NOT_QUEUE DBUS_NAME_FLAG_DO_NOT_QUEUE
     13 
     14 #define PRIMARY_OWNER DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
     15 #define IN_QUEUE DBUS_REQUEST_NAME_REPLY_IN_QUEUE
     16 #define EXISTS DBUS_REQUEST_NAME_REPLY_EXISTS
     17 #define ALREADY_OWNER DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER
     18 
     19 #define RELEASED DBUS_RELEASE_NAME_REPLY_RELEASED
     20 #define NON_EXISTANT DBUS_RELEASE_NAME_REPLY_NON_EXISTENT
     21 #define NOT_OWNER DBUS_RELEASE_NAME_REPLY_NOT_OWNER
     22 
     23 #define NUM_CONN 4
     24 #define TEST_NAME "org.freedesktop.DBus.TestSuite.NameTest"
     25 #define NUM_TRIES_TIL_FAIL 15
     26 
     27 typedef struct {
     28   int command;
     29 
     30   int connection_number;
     31   dbus_uint32_t flags;
     32 
     33   dbus_uint32_t expected_result;
     34 
     35   int expected_queue[NUM_CONN];
     36 } CommandAndResult;
     37 
     38 CommandAndResult test_data[] = {
     39         {ADD_CONNECTION, 0, ALLOW_REPLACEMENT | REPLACE_EXISTING,
     40 	PRIMARY_OWNER, {0,-1,-1,-1}},
     41 	{ADD_CONNECTION, 0, REPLACE_EXISTING,
     42 	ALREADY_OWNER, {0,-1,-1,-1}},
     43 	{ADD_CONNECTION, 1, ALLOW_REPLACEMENT | REPLACE_EXISTING,
     44 	IN_QUEUE, {0,1,-1,-1}},
     45 	{REMOVE_CONNECTION, 0, 0,
     46 	RELEASED, {1,-1,-1,-1}},
     47 	{ADD_CONNECTION, 0, REPLACE_EXISTING | DO_NOT_QUEUE,
     48 	PRIMARY_OWNER, {0,1,-1,-1}},
     49 	{ADD_CONNECTION, 2, ALLOW_REPLACEMENT,
     50 	IN_QUEUE, {0,1,2,-1}},
     51 	{ADD_CONNECTION, 2, ALLOW_REPLACEMENT | REPLACE_EXISTING,
     52 	IN_QUEUE, {0,2,1,-1}},
     53 	{ADD_CONNECTION, 0, ALLOW_REPLACEMENT | DO_NOT_QUEUE,
     54 	ALREADY_OWNER, {0,2,1,-1}},
     55 	{ADD_CONNECTION, 1, ALLOW_REPLACEMENT | REPLACE_EXISTING,
     56 	PRIMARY_OWNER, {1,2,-1,-1}},
     57 	{ADD_CONNECTION, 0, REPLACE_EXISTING,
     58 	PRIMARY_OWNER, {0,1,2,-1}},
     59 	{ADD_CONNECTION, 2, DO_NOT_QUEUE,
     60 	EXISTS, {0,1,-1,-1}},
     61 	{REMOVE_CONNECTION, 2, 0,
     62 	NOT_OWNER, {0,1,-1,-1}},
     63 	{ADD_CONNECTION, 3, 0,
     64 	IN_QUEUE, {0,1,3,-1}},
     65 	{ADD_CONNECTION, 0, ALLOW_REPLACEMENT,
     66 	ALREADY_OWNER, {0,1,3,-1}},
     67 	{ADD_CONNECTION, 2, ALLOW_REPLACEMENT,
     68 	IN_QUEUE, {0,1,3,2}}
     69 };
     70 
     71 static dbus_bool_t
     72 check_connection (DBusConnection *conn,
     73                   int iteration,
     74                   DBusConnection *uniq_conn[NUM_CONN])
     75 {
     76   DBusMessage *reply;
     77   DBusMessage *method;
     78   DBusError error;
     79   char **list;
     80   int len, i;
     81   const char *name;
     82 
     83   reply = NULL;
     84   method = NULL;
     85   list = NULL;
     86 
     87   dbus_error_init (&error);
     88 
     89   name = TEST_NAME;
     90   method = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
     91                                          DBUS_PATH_DBUS,
     92                                          DBUS_INTERFACE_DBUS,
     93                                          "ListQueuedOwners");
     94 
     95   if (method == NULL)
     96     goto out;
     97 
     98   if (!dbus_message_append_args (method,
     99                                  DBUS_TYPE_STRING, &name,
    100                                  DBUS_TYPE_INVALID))
    101     {
    102       fprintf (stderr, "Error appending args\n") ;
    103       goto out;
    104     }
    105 
    106   reply = dbus_connection_send_with_reply_and_block (conn,
    107                                                      method,
    108                                                      -1,
    109                                                      &error);
    110 
    111   if (reply == NULL)
    112     {
    113       fprintf (stderr, "Error calling ListQueuedOwners: %s\n", error.message);
    114       dbus_error_free (&error);
    115       goto out;
    116     }
    117 
    118 
    119 
    120   if (!dbus_message_get_args (reply,
    121                               &error,
    122                               DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
    123                               &list, &len,
    124                               DBUS_TYPE_INVALID))
    125     {
    126       fprintf (stderr, "Error getting args: %s\n", error.message);
    127       dbus_error_free (&error);
    128       goto out;
    129     }
    130 
    131   printf ("Iteration %i: ", iteration);
    132 
    133   if (len > NUM_CONN)
    134     {
    135       fprintf (stderr, "There are %i connections in the queue,"
    136                        " we are only expecting up to %i connections!\n",
    137 		       len,
    138 		       NUM_CONN);
    139       goto out;
    140     }
    141 
    142   for (i = 0; i < len; i++)
    143     {
    144       int expected_conn_num;
    145       const char *expected_uname;
    146 
    147       if (i > 0)
    148         printf (", ");
    149 
    150       printf ("%s", list[i]);
    151 
    152       expected_conn_num = test_data[iteration].expected_queue[i];
    153 
    154       if (expected_conn_num == -1)
    155         {
    156           fprintf (stderr,
    157                    "\nDid not expect this last connection"
    158                    " to be in the queue!\n");
    159           goto out;
    160         }
    161 
    162       expected_uname =
    163              dbus_bus_get_unique_name (uniq_conn[expected_conn_num]);
    164 
    165       if (strcmp (list[i], expected_uname) != 0)
    166         {
    167           fprintf (stderr,
    168                    "\n%s expected but %s is in the queue!\n",
    169                    expected_uname,
    170                    list[i]);
    171 
    172           goto out;
    173         }
    174     }
    175 
    176   printf ("\n");
    177 
    178   dbus_message_unref (method);
    179   dbus_message_unref (reply);
    180   dbus_free_string_array (list);
    181   return TRUE;
    182 
    183  out:
    184   if (method != NULL)
    185     dbus_message_unref (method);
    186 
    187   if (reply != NULL)
    188     dbus_message_unref (reply);
    189 
    190   if (list != NULL)
    191     dbus_free_string_array (list);
    192 
    193   return FALSE;
    194 }
    195 
    196 static dbus_bool_t
    197 match_acquired_or_lost_signal (DBusConnection *conn, const char *member, const char *name)
    198 {
    199   int tries;
    200   DBusMessage *msg;
    201   const char *interface = "org.freedesktop.DBus";
    202 
    203   for (tries = 0; tries < NUM_TRIES_TIL_FAIL; tries++)
    204     {
    205       _dbus_connection_lock (conn);
    206       _dbus_connection_do_iteration_unlocked (conn,
    207                                               DBUS_ITERATION_DO_READING |
    208                                               DBUS_ITERATION_DO_WRITING |
    209                                               DBUS_ITERATION_BLOCK,
    210                                               0);
    211       _dbus_connection_unlock (conn);
    212       msg = dbus_connection_pop_message (conn);
    213       if (msg != NULL)
    214         {
    215           if (dbus_message_is_signal (msg,
    216               interface,
    217               member))
    218             {
    219               const char *n;
    220               DBusError error;
    221               dbus_error_init (&error);
    222 
    223               dbus_message_get_args (msg, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID);
    224 
    225               if (dbus_error_is_set (&error))
    226                 {
    227                   fprintf (stderr, "Error getting args: %s\n", error.message);
    228                   dbus_error_free (&error);
    229                   dbus_message_unref (msg);
    230                   return FALSE;
    231                 }
    232 
    233               if (strcmp (n, name) == 0)
    234                 {
    235                   dbus_message_unref (msg);
    236                   break;
    237                 }
    238             }
    239           dbus_message_unref (msg);
    240         }
    241     }
    242 
    243   if (tries == NUM_TRIES_TIL_FAIL)
    244     {
    245       fprintf (stderr, "Did not recive the expected %s.%s signal!!!\n", interface, member);
    246       return FALSE;
    247     }
    248 
    249   return TRUE;
    250 }
    251 
    252 static dbus_bool_t
    253 match_name_owner_changed_signal (DBusConnection *conn, const char *bus_name, const char *lost_name, const char *acquired_name)
    254 {
    255   int tries;
    256   DBusMessage *msg;
    257 
    258   for (tries = 0; tries < NUM_TRIES_TIL_FAIL; tries++)
    259     {
    260       _dbus_connection_lock (conn);
    261       _dbus_connection_do_iteration_unlocked (conn,
    262                                               DBUS_ITERATION_DO_READING |
    263                                               DBUS_ITERATION_DO_WRITING |
    264                                               DBUS_ITERATION_BLOCK,
    265                                               0);
    266       _dbus_connection_unlock (conn);
    267       msg = dbus_connection_pop_message (conn);
    268 
    269       if (msg != NULL)
    270         {
    271           if (dbus_message_is_signal (msg,
    272               "org.freedesktop.DBus",
    273               "NameOwnerChanged"))
    274             {
    275               const char *n;
    276               const char *ln;
    277               const char *an;
    278               DBusError error;
    279               dbus_error_init (&error);
    280 
    281               dbus_message_get_args (msg, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_STRING, &ln, DBUS_TYPE_STRING, &an, DBUS_TYPE_INVALID);
    282 
    283               if (dbus_error_is_set (&error))
    284                 {
    285                   fprintf (stderr, "Error getting args: %s\n", error.message);
    286                   dbus_error_free (&error);
    287                   dbus_message_unref (msg);
    288                   return FALSE;
    289                 }
    290 
    291               if (strcmp (n, bus_name) == 0)
    292                 {
    293                   if ((lost_name == NULL && strcmp (ln, "") == 0)
    294                         || strcmp (lost_name, ln) == 0)
    295                     {
    296                       if ((acquired_name == NULL && strcmp (an, "") == 0)
    297                             || strcmp (acquired_name, an) == 0)
    298                         {
    299                           dbus_message_unref (msg);
    300                           break;
    301                         }
    302                       else
    303                         {
    304                           fprintf (stderr, "Error: name %s was expected to be acquired but we got %s instead\n", acquired_name, an);
    305                           dbus_message_unref (msg);
    306                           return FALSE;
    307                         }
    308                     }
    309                   else
    310                     {
    311                       fprintf (stderr, "Error: name %s was expected to be lost but we got %s instead\n", lost_name, ln);
    312                       dbus_message_unref (msg);
    313                       return FALSE;
    314                     }
    315                 }
    316             }
    317           dbus_message_unref (msg);
    318         }
    319     }
    320 
    321   if (tries == NUM_TRIES_TIL_FAIL)
    322     {
    323       fprintf (stderr, "Did not recive the expected NameOwnerChanged signal!!!\n");
    324       return FALSE;
    325     }
    326 
    327   return TRUE;
    328 }
    329 
    330 
    331 static dbus_bool_t
    332 check_signals (DBusConnection *monitor,
    333                int iteration,
    334                DBusConnection *conn[NUM_CONN])
    335 {
    336   DBusConnection *lost_conn = NULL;
    337   DBusConnection *acquired_conn = NULL;
    338   const char *lost_name;
    339   const char *acquired_name;
    340 
    341   if (iteration == 0)
    342     {
    343       int i;
    344       i = test_data[iteration].expected_queue[0];
    345 
    346       if (i >= 0)
    347         acquired_conn = conn[i];
    348     }
    349   else
    350     {
    351       int i;
    352       i = test_data[iteration - 1].expected_queue[0];
    353 
    354       if (i >= 0)
    355         lost_conn = conn[i];
    356 
    357       i = test_data[iteration].expected_queue[0];
    358 
    359       if (i >= 0)
    360         acquired_conn = conn[i];
    361 
    362       if (acquired_conn == lost_conn)
    363         acquired_conn = lost_conn = NULL;
    364     }
    365 
    366     lost_name = lost_conn == NULL? NULL :
    367                          dbus_bus_get_unique_name (lost_conn);
    368 
    369     acquired_name = acquired_conn == NULL? NULL :
    370                          dbus_bus_get_unique_name (acquired_conn);
    371 
    372     if (lost_name != NULL)
    373       if (!match_acquired_or_lost_signal (lost_conn,
    374                                          "NameLost",
    375                                          TEST_NAME))
    376         return FALSE;
    377 
    378     if (acquired_name != NULL)
    379       if (!match_acquired_or_lost_signal (acquired_conn,
    380                                          "NameAcquired",
    381                                          TEST_NAME))
    382         return FALSE;
    383 
    384     if (acquired_name != NULL || lost_name != NULL)
    385       if (!match_name_owner_changed_signal (monitor,
    386                                             TEST_NAME,
    387                                             lost_name,
    388                                             acquired_name))
    389         return FALSE;
    390 
    391     return TRUE;
    392 }
    393 
    394 int
    395 main (int argc, char *argv[])
    396 {
    397   DBusConnection *conn[NUM_CONN];
    398   DBusConnection *monitor;
    399   DBusError error;
    400   int i;
    401   int test_data_len;
    402 
    403   test_data_len = sizeof (test_data) / sizeof (CommandAndResult);
    404 
    405   dbus_error_init (&error);
    406 
    407   conn[0] = dbus_bus_get_private (DBUS_BUS_SESSION, &error);
    408   if (dbus_error_is_set (&error))
    409     {
    410       fprintf (stderr, "*** Failed to open connection 0 to session bus: %s\n",
    411                error.message);
    412       dbus_error_free (&error);
    413       return 1;
    414     }
    415 
    416   if (!match_acquired_or_lost_signal (conn[0],
    417                                 "NameAcquired",
    418                                 dbus_bus_get_unique_name (conn[0])))
    419     return 1;
    420 
    421   conn[1] = dbus_bus_get_private (DBUS_BUS_SESSION, &error);
    422   if (dbus_error_is_set (&error))
    423     {
    424       fprintf (stderr, "*** Failed to open connection 1 to session bus: %s\n",
    425                error.message);
    426       dbus_error_free (&error);
    427       return 1;
    428     }
    429 
    430   if (!match_acquired_or_lost_signal (conn[1],
    431                                 "NameAcquired",
    432                                 dbus_bus_get_unique_name (conn[1])))
    433     return 1;
    434 
    435 
    436   conn[2] = dbus_bus_get_private (DBUS_BUS_SESSION, &error);
    437   if (dbus_error_is_set (&error))
    438     {
    439       fprintf (stderr, "*** Failed to open connection 2 to session bus: %s\n",
    440                error.message);
    441       dbus_error_free (&error);
    442       return 1;
    443     }
    444 
    445   if (!match_acquired_or_lost_signal (conn[2],
    446                                 "NameAcquired",
    447                                 dbus_bus_get_unique_name (conn[2])))
    448     return 1;
    449 
    450 
    451   conn[3] = dbus_bus_get_private (DBUS_BUS_SESSION, &error);
    452   if (dbus_error_is_set (&error))
    453     {
    454       fprintf (stderr, "*** Failed to open connection 3 to session bus: %s\n",
    455                error.message);
    456       dbus_error_free (&error);
    457       return 1;
    458     }
    459 
    460   if (!match_acquired_or_lost_signal (conn[3],
    461                                 "NameAcquired",
    462                                 dbus_bus_get_unique_name (conn[3])))
    463     return 1;
    464 
    465 
    466   monitor = dbus_bus_get (DBUS_BUS_SESSION, &error);
    467   if (dbus_error_is_set (&error))
    468     {
    469       fprintf (stderr, "*** Failed to open monitoring connection to session bus: %s\n",
    470                error.message);
    471       dbus_error_free (&error);
    472       return 1;
    473     }
    474 
    475   if (!match_acquired_or_lost_signal (monitor,
    476                                 "NameAcquired",
    477                                 dbus_bus_get_unique_name (monitor)))
    478     return 1;
    479 
    480   dbus_bus_add_match (monitor, "", &error);
    481   if (dbus_error_is_set (&error))
    482     {
    483       fprintf (stderr, "*** Failed to set filter on monitoring connection: %s\n",
    484                error.message);
    485       dbus_error_free (&error);
    486       return 1;
    487     }
    488 
    489 
    490   for (i = 0; i < NUM_CONN; i++)
    491     dbus_connection_set_exit_on_disconnect (conn[i], FALSE);
    492 
    493   for (i = 0; i < test_data_len; i++)
    494     {
    495       dbus_uint32_t result;
    496       result = 0;
    497 
    498       if (test_data[i].command == ADD_CONNECTION)
    499         {
    500           result = dbus_bus_request_name (conn[test_data[i].connection_number],
    501                                           TEST_NAME,
    502                                           test_data[i].flags,
    503                                           &error);
    504 
    505           if (dbus_error_is_set (&error))
    506             {
    507               fprintf (stderr, "Error on addition in iteration %i: %s\n", i, error.message);
    508               dbus_error_free (&error);
    509               return 1;
    510             }
    511         }
    512       else if (test_data[i].command == REMOVE_CONNECTION)
    513         {
    514           result = dbus_bus_release_name (conn[test_data[i].connection_number],
    515                                           TEST_NAME,
    516                                           &error);
    517           if (dbus_error_is_set (&error))
    518             {
    519               fprintf (stderr, "*** Failed to remove connection %i in iteration %i: %s\n",
    520                        test_data[i].connection_number,
    521                        i,
    522                        error.message);
    523               dbus_error_free (&error);
    524               return 1;
    525             }
    526         }
    527       else
    528         {
    529           fprintf (stderr, "Command #%i not a valid command!\n", test_data[i].command);
    530           return 1;
    531         }
    532 
    533 
    534       if (result != test_data[i].expected_result)
    535         {
    536           fprintf (stderr, "Results recived (%i) are not the expected results (%i) in iteration %i\n",
    537                    result,
    538                    test_data[i].expected_result,
    539                    i);
    540           return 1;
    541         }
    542 
    543       if (!check_connection (monitor, i, conn))
    544         {
    545           fprintf (stderr, "Failed at iteration %i\n", i);
    546           return 1;
    547         }
    548 
    549       if (!check_signals (monitor, i, conn))
    550         {
    551           fprintf (stderr, "Failed at iteration %i\n", i);
    552           return 1;
    553         }
    554     }
    555 
    556     return 0;
    557 }
    558