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