* configure.in: Add test/name-test/Makefile to the generated
[platform/upstream/dbus.git] / test / name-test / test-names.c
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 extern const char *dbus_bus_connection_get_unique_name (DBusConnection *connection);
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 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_connection_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 void
199 clear_message_queue (DBusConnection *conn)
200 {
201   int tries;
202   DBusMessage *msg;
203
204   for (tries = 0; tries < NUM_TRIES_TIL_FAIL; tries++)
205     {
206       _dbus_connection_lock (conn);
207       _dbus_connection_do_iteration_unlocked (conn,
208                                               DBUS_ITERATION_DO_READING |
209                                               DBUS_ITERATION_DO_WRITING |
210                                               DBUS_ITERATION_BLOCK,
211                                               0);
212       _dbus_connection_unlock (conn);
213       msg = dbus_connection_pop_message (conn);
214    } 
215 }
216
217 static dbus_bool_t
218 match_acquired_or_lost_signal (DBusConnection *conn, const char *member, const char *name)
219 {
220   int tries;
221   DBusMessage *msg;
222   const char *interface = "org.freedesktop.DBus";
223
224   for (tries = 0; tries < NUM_TRIES_TIL_FAIL; tries++)
225     {
226       _dbus_connection_lock (conn);
227       _dbus_connection_do_iteration_unlocked (conn,
228                                               DBUS_ITERATION_DO_READING |
229                                               DBUS_ITERATION_DO_WRITING |
230                                               DBUS_ITERATION_BLOCK,
231                                               0);
232       _dbus_connection_unlock (conn);
233       msg = dbus_connection_pop_message (conn);
234       if (msg != NULL)
235         {
236           if (dbus_message_is_signal (msg, 
237               interface,
238               member))
239             {
240               const char *n;
241               DBusError error;
242               dbus_error_init (&error);
243
244               dbus_message_get_args (msg, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID);
245
246               if (dbus_error_is_set (&error))
247                 {
248                   fprintf (stderr, "Error getting args: %s\n", error.message);
249                   dbus_error_free (&error);
250                   dbus_message_unref (msg);
251                   return FALSE;
252                 }
253
254               if (strcmp (n, name) == 0)
255                 {
256                   dbus_message_unref (msg); 
257                   break;
258                 }
259             }
260           dbus_message_unref (msg);
261         }
262     }
263
264   if (tries == NUM_TRIES_TIL_FAIL)
265     {
266       fprintf (stderr, "Did not recive the expected %s.%s signal!!!\n", interface, member);
267       return FALSE;
268     }
269   
270   return TRUE;
271 }
272
273 static dbus_bool_t
274 match_name_owner_changed_signal (DBusConnection *conn, const char *bus_name, const char *lost_name, const char *acquired_name)
275 {
276   int tries;
277   DBusMessage *msg;
278  
279   for (tries = 0; tries < NUM_TRIES_TIL_FAIL; tries++)
280     {
281       _dbus_connection_lock (conn);
282       _dbus_connection_do_iteration_unlocked (conn,
283                                               DBUS_ITERATION_DO_READING |
284                                               DBUS_ITERATION_DO_WRITING |
285                                               DBUS_ITERATION_BLOCK,
286                                               0);
287       _dbus_connection_unlock (conn);
288       msg = dbus_connection_pop_message (conn);
289     
290       if (msg != NULL)
291         {
292           if (dbus_message_is_signal (msg, 
293               "org.freedesktop.DBus",
294               "NameOwnerChanged"))
295             {
296               const char *n;
297               const char *ln;
298               const char *an;
299               DBusError error;
300               dbus_error_init (&error);
301
302               dbus_message_get_args (msg, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_STRING, &ln, DBUS_TYPE_STRING, &an, DBUS_TYPE_INVALID);
303
304               if (dbus_error_is_set (&error))
305                 {
306                   fprintf (stderr, "Error getting args: %s\n", error.message);
307                   dbus_error_free (&error);
308                   dbus_message_unref (msg);
309                   return FALSE;
310                 }
311
312               if (strcmp (n, bus_name) == 0)
313                 {
314                   if ((lost_name == NULL && strcmp (ln, "") == 0)
315                         || strcmp (lost_name, ln) == 0)
316                     {
317                       if ((acquired_name == NULL && strcmp (an, "") == 0)
318                             || strcmp (acquired_name, an) == 0)
319                         {
320                           dbus_message_unref (msg); 
321                           break;
322                         }
323                       else
324                         {
325                           fprintf (stderr, "Error: name %s was expected to be acquired but we got %s instead\n", acquired_name, an);
326                           dbus_message_unref (msg);
327                           return FALSE;
328                         }
329                     }
330                   else
331                     {
332                       fprintf (stderr, "Error: name %s was expected to be lost but we got %s instead\n", lost_name, ln);
333                       dbus_message_unref (msg);
334                       return FALSE;
335                     }
336                 }
337             }
338           dbus_message_unref (msg);
339         }
340     }
341
342   if (tries == NUM_TRIES_TIL_FAIL)
343     {
344       fprintf (stderr, "Did not recive the expected NameOwnerChanged signal!!!\n");
345       return FALSE;
346     }
347   
348   return TRUE;
349 }
350
351
352 static dbus_bool_t 
353 check_signals (DBusConnection *monitor,
354                int iteration,
355                DBusConnection *conn[NUM_CONN])
356 {
357   DBusConnection *lost_conn = NULL;
358   DBusConnection *acquired_conn = NULL;
359   const char *lost_name;
360   const char *acquired_name;
361   
362   if (iteration == 0)
363     {
364       int i;
365       i = test_data[iteration].expected_queue[0];
366
367       if (i >= 0)
368         acquired_conn = conn[i];
369     }
370   else
371     {
372       int i;
373       i = test_data[iteration - 1].expected_queue[0];
374
375       if (i >= 0)
376         lost_conn = conn[i];
377
378       i = test_data[iteration].expected_queue[0];
379
380       if (i >= 0)
381         acquired_conn = conn[i];
382
383       if (acquired_conn == lost_conn)
384         acquired_conn = lost_conn = NULL;
385     }
386
387     lost_name = lost_conn == NULL? NULL : 
388                          dbus_bus_connection_get_unique_name (lost_conn);
389
390     acquired_name = acquired_conn == NULL? NULL :
391                          dbus_bus_connection_get_unique_name (acquired_conn);
392
393     if (lost_name != NULL)
394       if (!match_acquired_or_lost_signal (lost_conn,
395                                          "NameLost",
396                                          TEST_NAME))
397         return FALSE;
398
399     if (acquired_name != NULL)
400       if (!match_acquired_or_lost_signal (acquired_conn,
401                                          "NameAcquired",
402                                          TEST_NAME))
403         return FALSE;
404
405     if (acquired_name != NULL || lost_name != NULL)
406       if (!match_name_owner_changed_signal (monitor,
407                                             TEST_NAME,
408                                             lost_name,
409                                             acquired_name))
410         return FALSE;
411     
412     return TRUE;
413 }
414
415 int
416 main (int argc, char *argv[])
417 {
418   DBusConnection *conn[NUM_CONN];
419   DBusConnection *monitor;
420   DBusError error;
421   int i;
422   int test_data_len;
423
424   test_data_len = sizeof (test_data) / sizeof (CommandAndResult);
425   
426   dbus_error_init (&error);
427
428   conn[0] = dbus_bus_get_private (DBUS_BUS_SESSION, &error);
429   if (dbus_error_is_set (&error))
430     {
431       fprintf (stderr, "*** Failed to open connection 0 to session bus: %s\n",
432                error.message);
433       dbus_error_free (&error);
434       return 1;
435     }
436   
437   if (!match_acquired_or_lost_signal (conn[0],
438                                 "NameAcquired",
439                                 dbus_bus_connection_get_unique_name (conn[0])))
440     return 1;
441   
442   conn[1] = dbus_bus_get_private (DBUS_BUS_SESSION, &error);
443   if (dbus_error_is_set (&error))
444     {
445       fprintf (stderr, "*** Failed to open connection 1 to session bus: %s\n",
446                error.message);
447       dbus_error_free (&error);
448       return 1;
449     }
450
451   if (!match_acquired_or_lost_signal (conn[1],
452                                 "NameAcquired",
453                                 dbus_bus_connection_get_unique_name (conn[1])))
454     return 1;
455
456
457   conn[2] = dbus_bus_get_private (DBUS_BUS_SESSION, &error);
458   if (dbus_error_is_set (&error))
459     {
460       fprintf (stderr, "*** Failed to open connection 2 to session bus: %s\n",
461                error.message);
462       dbus_error_free (&error);
463       return 1;
464     }
465
466   if (!match_acquired_or_lost_signal (conn[2],
467                                 "NameAcquired",
468                                 dbus_bus_connection_get_unique_name (conn[2])))
469     return 1;
470
471
472   conn[3] = dbus_bus_get_private (DBUS_BUS_SESSION, &error);
473   if (dbus_error_is_set (&error))
474     {
475       fprintf (stderr, "*** Failed to open connection 3 to session bus: %s\n",
476                error.message);
477       dbus_error_free (&error);
478       return 1;
479     }
480
481   if (!match_acquired_or_lost_signal (conn[3],
482                                 "NameAcquired",
483                                 dbus_bus_connection_get_unique_name (conn[3])))
484     return 1;
485
486
487   monitor = dbus_bus_get (DBUS_BUS_SESSION, &error);
488   if (dbus_error_is_set (&error))
489     {
490       fprintf (stderr, "*** Failed to open monitoring connection to session bus: %s\n",
491                error.message);
492       dbus_error_free (&error);
493       return 1;
494     }
495
496   if (!match_acquired_or_lost_signal (monitor,
497                                 "NameAcquired",
498                                 dbus_bus_connection_get_unique_name (monitor)))
499     return 1;
500
501   dbus_bus_add_match (monitor, "", &error);
502   if (dbus_error_is_set (&error))
503     {
504       fprintf (stderr, "*** Failed to set filter on monitoring connection: %s\n",
505                error.message);
506       dbus_error_free (&error);
507       return 1;
508     }
509
510
511   for (i = 0; i < NUM_CONN; i++) 
512     dbus_connection_set_exit_on_disconnect (conn[i], FALSE);
513
514   for (i = 0; i < test_data_len; i++)
515     {
516       dbus_uint32_t result;
517       result = 0;
518
519       if (test_data[i].command == ADD_CONNECTION)
520         {
521           result = dbus_bus_request_name (conn[test_data[i].connection_number], 
522                                           TEST_NAME, 
523                                           test_data[i].flags,
524                                           &error);
525
526           if (dbus_error_is_set (&error))
527             {
528               fprintf (stderr, "Error on addition in iteration %i: %s\n", i, error.message);
529               dbus_error_free (&error);
530               return 1;
531             }
532         } 
533       else if (test_data[i].command == REMOVE_CONNECTION)
534         {
535           result = dbus_bus_release_name (conn[test_data[i].connection_number], 
536                                           TEST_NAME, 
537                                           &error);  
538           if (dbus_error_is_set (&error))
539             {
540               fprintf (stderr, "*** Failed to remove connection %i in iteration %i: %s\n",
541                        test_data[i].connection_number,
542                        i,
543                        error.message);
544               dbus_error_free (&error);
545               return 1;
546             }
547         }
548       else
549         {
550           fprintf (stderr, "Command #%i not a valid command!\n", test_data[i].command);
551           return 1;
552         }
553
554
555       if (result != test_data[i].expected_result)
556         {
557           fprintf (stderr, "Results recived (%i) are not the expected results (%i) in iteration %i\n",
558                    result,
559                    test_data[i].expected_result,
560                    i);
561           return 1;
562         }
563
564       if (!check_connection (monitor, i, conn))
565         {
566           fprintf (stderr, "Failed at iteration %i\n", i);
567           return 1;
568         }
569
570       if (!check_signals (monitor, i, conn))
571         {
572           fprintf (stderr, "Failed at iteration %i\n", i);
573           return 1;
574         }
575     }
576
577     return 0;
578 }