• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dispatch.c  Message dispatcher
3  *
4  * Copyright (C) 2003  CodeFactory AB
5  * Copyright (C) 2003, 2004, 2005  Red Hat, Inc.
6  * Copyright (C) 2004  Imendio HB
7  *
8  * Licensed under the Academic Free License version 2.1
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  */
25 
26 #include "dispatch.h"
27 #include "connection.h"
28 #include "driver.h"
29 #include "services.h"
30 #include "activation.h"
31 #include "utils.h"
32 #include "bus.h"
33 #include "signals.h"
34 #include "test.h"
35 #include <dbus/dbus-internals.h>
36 #include <string.h>
37 
38 static dbus_bool_t
send_one_message(DBusConnection * connection,BusContext * context,DBusConnection * sender,DBusConnection * addressed_recipient,DBusMessage * message,BusTransaction * transaction,DBusError * error)39 send_one_message (DBusConnection *connection,
40                   BusContext     *context,
41                   DBusConnection *sender,
42                   DBusConnection *addressed_recipient,
43                   DBusMessage    *message,
44                   BusTransaction *transaction,
45                   DBusError      *error)
46 {
47   if (!bus_context_check_security_policy (context, transaction,
48                                           sender,
49                                           addressed_recipient,
50                                           connection,
51                                           message,
52                                           NULL))
53     return TRUE; /* silently don't send it */
54 
55   if (!bus_transaction_send (transaction,
56                              connection,
57                              message))
58     {
59       BUS_SET_OOM (error);
60       return FALSE;
61     }
62 
63   return TRUE;
64 }
65 
66 dbus_bool_t
bus_dispatch_matches(BusTransaction * transaction,DBusConnection * sender,DBusConnection * addressed_recipient,DBusMessage * message,DBusError * error)67 bus_dispatch_matches (BusTransaction *transaction,
68                       DBusConnection *sender,
69                       DBusConnection *addressed_recipient,
70                       DBusMessage    *message,
71                       DBusError      *error)
72 {
73   DBusError tmp_error;
74   BusConnections *connections;
75   DBusList *recipients;
76   BusMatchmaker *matchmaker;
77   DBusList *link;
78   BusContext *context;
79 
80   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
81 
82   /* sender and recipient can both be NULL for the bus driver,
83    * or for signals with no particular recipient
84    */
85 
86   _dbus_assert (sender == NULL || bus_connection_is_active (sender));
87   _dbus_assert (dbus_message_get_sender (message) != NULL);
88 
89   connections = bus_transaction_get_connections (transaction);
90 
91   dbus_error_init (&tmp_error);
92   context = bus_transaction_get_context (transaction);
93   matchmaker = bus_context_get_matchmaker (context);
94 
95   recipients = NULL;
96   if (!bus_matchmaker_get_recipients (matchmaker, connections,
97                                       sender, addressed_recipient, message,
98                                       &recipients))
99     {
100       BUS_SET_OOM (error);
101       return FALSE;
102     }
103 
104   link = _dbus_list_get_first_link (&recipients);
105   while (link != NULL)
106     {
107       DBusConnection *dest;
108 
109       dest = link->data;
110 
111       if (!send_one_message (dest, context, sender, addressed_recipient,
112                              message, transaction, &tmp_error))
113         break;
114 
115       link = _dbus_list_get_next_link (&recipients, link);
116     }
117 
118   _dbus_list_clear (&recipients);
119 
120   if (dbus_error_is_set (&tmp_error))
121     {
122       dbus_move_error (&tmp_error, error);
123       return FALSE;
124     }
125   else
126     return TRUE;
127 }
128 
129 static DBusHandlerResult
bus_dispatch(DBusConnection * connection,DBusMessage * message)130 bus_dispatch (DBusConnection *connection,
131               DBusMessage    *message)
132 {
133   const char *sender, *service_name;
134   DBusError error;
135   BusTransaction *transaction;
136   BusContext *context;
137   DBusHandlerResult result;
138   DBusConnection *addressed_recipient;
139 
140   result = DBUS_HANDLER_RESULT_HANDLED;
141 
142   transaction = NULL;
143   addressed_recipient = NULL;
144   dbus_error_init (&error);
145 
146   context = bus_connection_get_context (connection);
147   _dbus_assert (context != NULL);
148 
149   /* If we can't even allocate an OOM error, we just go to sleep
150    * until we can.
151    */
152   while (!bus_connection_preallocate_oom_error (connection))
153     _dbus_wait_for_memory ();
154 
155   /* Ref connection in case we disconnect it at some point in here */
156   dbus_connection_ref (connection);
157 
158   service_name = dbus_message_get_destination (message);
159 
160 #ifdef DBUS_ENABLE_VERBOSE_MODE
161   {
162     const char *interface_name, *member_name, *error_name;
163 
164     interface_name = dbus_message_get_interface (message);
165     member_name = dbus_message_get_member (message);
166     error_name = dbus_message_get_error_name (message);
167 
168     _dbus_verbose ("DISPATCH: %s %s %s to %s\n",
169                    interface_name ? interface_name : "(no interface)",
170                    member_name ? member_name : "(no member)",
171                    error_name ? error_name : "(no error name)",
172                    service_name ? service_name : "peer");
173   }
174 #endif /* DBUS_ENABLE_VERBOSE_MODE */
175 
176   /* If service_name is NULL, if it's a signal we send it to all
177    * connections with a match rule. If it's not a signal, there
178    * are some special cases here but mostly we just bail out.
179    */
180   if (service_name == NULL)
181     {
182       if (dbus_message_is_signal (message,
183                                   DBUS_INTERFACE_LOCAL,
184                                   "Disconnected"))
185         {
186           bus_connection_disconnected (connection);
187           goto out;
188         }
189 
190       if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
191         {
192           /* DBusConnection also handles some of these automatically, we leave
193            * it to do so.
194            */
195           result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
196           goto out;
197         }
198     }
199 
200   /* Create our transaction */
201   transaction = bus_transaction_new (context);
202   if (transaction == NULL)
203     {
204       BUS_SET_OOM (&error);
205       goto out;
206     }
207 
208   /* Assign a sender to the message */
209   if (bus_connection_is_active (connection))
210     {
211       sender = bus_connection_get_name (connection);
212       _dbus_assert (sender != NULL);
213 
214       if (!dbus_message_set_sender (message, sender))
215         {
216           BUS_SET_OOM (&error);
217           goto out;
218         }
219 
220       /* We need to refetch the service name here, because
221        * dbus_message_set_sender can cause the header to be
222        * reallocated, and thus the service_name pointer will become
223        * invalid.
224        */
225       service_name = dbus_message_get_destination (message);
226     }
227 
228   if (service_name &&
229       strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
230     {
231       if (!bus_context_check_security_policy (context, transaction,
232                                               connection, NULL, NULL, message, &error))
233         {
234           _dbus_verbose ("Security policy rejected message\n");
235           goto out;
236         }
237 
238       _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS);
239       if (!bus_driver_handle_message (connection, transaction, message, &error))
240         goto out;
241     }
242   else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
243     {
244       _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
245       dbus_connection_close (connection);
246       goto out;
247     }
248   else if (service_name != NULL) /* route to named service */
249     {
250       DBusString service_string;
251       BusService *service;
252       BusRegistry *registry;
253 
254       _dbus_assert (service_name != NULL);
255 
256       registry = bus_connection_get_registry (connection);
257 
258       _dbus_string_init_const (&service_string, service_name);
259       service = bus_registry_lookup (registry, &service_string);
260 
261       if (service == NULL && dbus_message_get_auto_start (message))
262         {
263           BusActivation *activation;
264           /* We can't do the security policy check here, since the addressed
265            * recipient service doesn't exist yet. We do it before sending the
266            * message after the service has been created.
267            */
268           activation = bus_connection_get_activation (connection);
269 
270           if (!bus_activation_activate_service (activation, connection, transaction, TRUE,
271                                                 message, service_name, &error))
272             {
273               _DBUS_ASSERT_ERROR_IS_SET (&error);
274               _dbus_verbose ("bus_activation_activate_service() failed: %s\n", error.name);
275               goto out;
276             }
277 
278           goto out;
279         }
280       else if (service == NULL)
281         {
282           dbus_set_error (&error,
283                           DBUS_ERROR_NAME_HAS_NO_OWNER,
284                           "Name \"%s\" does not exist",
285                           service_name);
286           goto out;
287         }
288       else
289         {
290           addressed_recipient = bus_service_get_primary_owners_connection (service);
291           _dbus_assert (addressed_recipient != NULL);
292 
293           if (!bus_context_check_security_policy (context, transaction,
294                                                   connection, addressed_recipient,
295                                                   addressed_recipient,
296                                                   message, &error))
297             goto out;
298 
299           /* Dispatch the message */
300           if (!bus_transaction_send (transaction, addressed_recipient, message))
301             {
302               BUS_SET_OOM (&error);
303               goto out;
304             }
305         }
306     }
307 
308   /* Now match the messages against any match rules, which will send
309    * out signals and such. addressed_recipient may == NULL.
310    */
311   if (!bus_dispatch_matches (transaction, connection, addressed_recipient, message, &error))
312     goto out;
313 
314  out:
315   if (dbus_error_is_set (&error))
316     {
317       if (!dbus_connection_get_is_connected (connection))
318         {
319           /* If we disconnected it, we won't bother to send it any error
320            * messages.
321            */
322           _dbus_verbose ("Not sending error to connection we disconnected\n");
323         }
324       else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
325         {
326           bus_connection_send_oom_error (connection, message);
327 
328           /* cancel transaction due to OOM */
329           if (transaction != NULL)
330             {
331               bus_transaction_cancel_and_free (transaction);
332               transaction = NULL;
333             }
334         }
335       else
336         {
337           /* Try to send the real error, if no mem to do that, send
338            * the OOM error
339            */
340           _dbus_assert (transaction != NULL);
341           if (!bus_transaction_send_error_reply (transaction, connection,
342                                                  &error, message))
343             {
344               bus_connection_send_oom_error (connection, message);
345 
346               /* cancel transaction due to OOM */
347               if (transaction != NULL)
348                 {
349                   bus_transaction_cancel_and_free (transaction);
350                   transaction = NULL;
351                 }
352             }
353         }
354 
355 
356       dbus_error_free (&error);
357     }
358 
359   if (transaction != NULL)
360     {
361       bus_transaction_execute_and_free (transaction);
362     }
363 
364   dbus_connection_unref (connection);
365 
366   return result;
367 }
368 
369 static DBusHandlerResult
bus_dispatch_message_filter(DBusConnection * connection,DBusMessage * message,void * user_data)370 bus_dispatch_message_filter (DBusConnection     *connection,
371                              DBusMessage        *message,
372                              void               *user_data)
373 {
374   return bus_dispatch (connection, message);
375 }
376 
377 dbus_bool_t
bus_dispatch_add_connection(DBusConnection * connection)378 bus_dispatch_add_connection (DBusConnection *connection)
379 {
380   if (!dbus_connection_add_filter (connection,
381                                    bus_dispatch_message_filter,
382                                    NULL, NULL))
383     return FALSE;
384 
385   return TRUE;
386 }
387 
388 void
bus_dispatch_remove_connection(DBusConnection * connection)389 bus_dispatch_remove_connection (DBusConnection *connection)
390 {
391   /* Here we tell the bus driver that we want to get off. */
392   bus_driver_remove_connection (connection);
393 
394   dbus_connection_remove_filter (connection,
395                                  bus_dispatch_message_filter,
396                                  NULL);
397 }
398 
399 #ifdef DBUS_BUILD_TESTS
400 
401 #include <stdio.h>
402 
403 /* This is used to know whether we need to block in order to finish
404  * sending a message, or whether the initial dbus_connection_send()
405  * already flushed the queue.
406  */
407 #define SEND_PENDING(connection) (dbus_connection_has_messages_to_send (connection))
408 
409 typedef dbus_bool_t (* Check1Func) (BusContext     *context);
410 typedef dbus_bool_t (* Check2Func) (BusContext     *context,
411                                     DBusConnection *connection);
412 
413 static dbus_bool_t check_no_leftovers (BusContext *context);
414 
415 static void
block_connection_until_message_from_bus(BusContext * context,DBusConnection * connection,const char * what_is_expected)416 block_connection_until_message_from_bus (BusContext     *context,
417                                          DBusConnection *connection,
418                                          const char     *what_is_expected)
419 {
420   _dbus_verbose ("expecting: %s\n", what_is_expected);
421 
422   while (dbus_connection_get_dispatch_status (connection) ==
423          DBUS_DISPATCH_COMPLETE &&
424          dbus_connection_get_is_connected (connection))
425     {
426       bus_test_run_bus_loop (context, TRUE);
427       bus_test_run_clients_loop (FALSE);
428     }
429 }
430 
431 static void
spin_connection_until_authenticated(BusContext * context,DBusConnection * connection)432 spin_connection_until_authenticated (BusContext     *context,
433                                      DBusConnection *connection)
434 {
435   _dbus_verbose ("Spinning to auth connection %p\n", connection);
436   while (!dbus_connection_get_is_authenticated (connection) &&
437          dbus_connection_get_is_connected (connection))
438     {
439       bus_test_run_bus_loop (context, FALSE);
440       bus_test_run_clients_loop (FALSE);
441     }
442   _dbus_verbose (" ... done spinning to auth connection %p\n", connection);
443 }
444 
445 /* compensate for fact that pop_message() can return #NULL due to OOM */
446 static DBusMessage*
pop_message_waiting_for_memory(DBusConnection * connection)447 pop_message_waiting_for_memory (DBusConnection *connection)
448 {
449   while (dbus_connection_get_dispatch_status (connection) ==
450          DBUS_DISPATCH_NEED_MEMORY)
451     _dbus_wait_for_memory ();
452 
453   return dbus_connection_pop_message (connection);
454 }
455 
456 static DBusMessage*
borrow_message_waiting_for_memory(DBusConnection * connection)457 borrow_message_waiting_for_memory (DBusConnection *connection)
458 {
459   while (dbus_connection_get_dispatch_status (connection) ==
460          DBUS_DISPATCH_NEED_MEMORY)
461     _dbus_wait_for_memory ();
462 
463   return dbus_connection_borrow_message (connection);
464 }
465 
466 static void
warn_unexpected_real(DBusConnection * connection,DBusMessage * message,const char * expected,const char * function,int line)467 warn_unexpected_real (DBusConnection *connection,
468                       DBusMessage    *message,
469                       const char     *expected,
470                       const char     *function,
471                       int             line)
472 {
473   if (message)
474     _dbus_warn ("%s:%d received message interface \"%s\" member \"%s\" error name \"%s\" on %p, expecting %s\n",
475                 function, line,
476                 dbus_message_get_interface (message) ?
477                 dbus_message_get_interface (message) : "(unset)",
478                 dbus_message_get_member (message) ?
479                 dbus_message_get_member (message) : "(unset)",
480                 dbus_message_get_error_name (message) ?
481                 dbus_message_get_error_name (message) : "(unset)",
482                 connection,
483                 expected);
484   else
485     _dbus_warn ("%s:%d received no message on %p, expecting %s\n",
486                 function, line, connection, expected);
487 }
488 
489 #define warn_unexpected(connection, message, expected) \
490   warn_unexpected_real (connection, message, expected, _DBUS_FUNCTION_NAME, __LINE__)
491 
492 static void
verbose_message_received(DBusConnection * connection,DBusMessage * message)493 verbose_message_received (DBusConnection *connection,
494                           DBusMessage    *message)
495 {
496   _dbus_verbose ("Received message interface \"%s\" member \"%s\" error name \"%s\" on %p\n",
497                  dbus_message_get_interface (message) ?
498                  dbus_message_get_interface (message) : "(unset)",
499                  dbus_message_get_member (message) ?
500                  dbus_message_get_member (message) : "(unset)",
501                  dbus_message_get_error_name (message) ?
502                  dbus_message_get_error_name (message) : "(unset)",
503                  connection);
504 }
505 
506 typedef enum
507 {
508   SERVICE_CREATED,
509   OWNER_CHANGED,
510   SERVICE_DELETED
511 } ServiceInfoKind;
512 
513 typedef struct
514 {
515   ServiceInfoKind expected_kind;
516   const char *expected_service_name;
517   dbus_bool_t failed;
518   DBusConnection *skip_connection;
519 } CheckServiceOwnerChangedData;
520 
521 static dbus_bool_t
check_service_owner_changed_foreach(DBusConnection * connection,void * data)522 check_service_owner_changed_foreach (DBusConnection *connection,
523                                      void           *data)
524 {
525   CheckServiceOwnerChangedData *d = data;
526   DBusMessage *message;
527   DBusError error;
528   const char *service_name, *old_owner, *new_owner;
529 
530   if (d->expected_kind == SERVICE_CREATED
531       && connection == d->skip_connection)
532     return TRUE;
533 
534   dbus_error_init (&error);
535   d->failed = TRUE;
536 
537   message = pop_message_waiting_for_memory (connection);
538   if (message == NULL)
539     {
540       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
541                   connection, "NameOwnerChanged");
542       goto out;
543     }
544   else if (!dbus_message_is_signal (message,
545                                     DBUS_INTERFACE_DBUS,
546                                     "NameOwnerChanged"))
547     {
548       warn_unexpected (connection, message, "NameOwnerChanged");
549 
550       goto out;
551     }
552   else
553     {
554     reget_service_info_data:
555       service_name = NULL;
556       old_owner = NULL;
557       new_owner = NULL;
558 
559       dbus_message_get_args (message, &error,
560                              DBUS_TYPE_STRING, &service_name,
561                              DBUS_TYPE_STRING, &old_owner,
562                              DBUS_TYPE_STRING, &new_owner,
563                              DBUS_TYPE_INVALID);
564 
565       if (dbus_error_is_set (&error))
566         {
567           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
568             {
569               dbus_error_free (&error);
570               _dbus_wait_for_memory ();
571               goto reget_service_info_data;
572             }
573           else
574             {
575               _dbus_warn ("Did not get the expected arguments\n");
576               goto out;
577             }
578         }
579 
580       if ((d->expected_kind == SERVICE_CREATED    && ( old_owner[0] || !new_owner[0]))
581           || (d->expected_kind == OWNER_CHANGED   && (!old_owner[0] || !new_owner[0]))
582           || (d->expected_kind == SERVICE_DELETED && (!old_owner[0] ||  new_owner[0])))
583         {
584           _dbus_warn ("inconsistent NameOwnerChanged arguments\n");
585           goto out;
586         }
587 
588       if (strcmp (service_name, d->expected_service_name) != 0)
589         {
590           _dbus_warn ("expected info on service %s, got info on %s\n",
591                       d->expected_service_name,
592                       service_name);
593           goto out;
594         }
595 
596       if (*service_name == ':' && new_owner[0]
597           && strcmp (service_name, new_owner) != 0)
598         {
599           _dbus_warn ("inconsistent ServiceOwnedChanged message (\"%s\" [ %s -> %s ])\n",
600                       service_name, old_owner, new_owner);
601           goto out;
602         }
603     }
604 
605   d->failed = FALSE;
606 
607  out:
608   dbus_error_free (&error);
609 
610   if (message)
611     dbus_message_unref (message);
612 
613   return !d->failed;
614 }
615 
616 
617 static void
kill_client_connection(BusContext * context,DBusConnection * connection)618 kill_client_connection (BusContext     *context,
619                         DBusConnection *connection)
620 {
621   char *base_service;
622   const char *s;
623   CheckServiceOwnerChangedData socd;
624 
625   _dbus_verbose ("killing connection %p\n", connection);
626 
627   s = dbus_bus_get_unique_name (connection);
628   _dbus_assert (s != NULL);
629 
630   while ((base_service = _dbus_strdup (s)) == NULL)
631     _dbus_wait_for_memory ();
632 
633   dbus_connection_ref (connection);
634 
635   /* kick in the disconnect handler that unrefs the connection */
636   dbus_connection_close (connection);
637 
638   bus_test_run_everything (context);
639 
640   _dbus_assert (bus_test_client_listed (connection));
641 
642   /* Run disconnect handler in test.c */
643   if (bus_connection_dispatch_one_message (connection))
644     _dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
645 
646   _dbus_assert (!dbus_connection_get_is_connected (connection));
647   dbus_connection_unref (connection);
648   connection = NULL;
649   _dbus_assert (!bus_test_client_listed (connection));
650 
651   socd.expected_kind = SERVICE_DELETED;
652   socd.expected_service_name = base_service;
653   socd.failed = FALSE;
654   socd.skip_connection = NULL;
655 
656   bus_test_clients_foreach (check_service_owner_changed_foreach,
657                             &socd);
658 
659   dbus_free (base_service);
660 
661   if (socd.failed)
662     _dbus_assert_not_reached ("didn't get the expected NameOwnerChanged (deletion) messages");
663 
664   if (!check_no_leftovers (context))
665     _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
666 }
667 
668 static void
kill_client_connection_unchecked(DBusConnection * connection)669 kill_client_connection_unchecked (DBusConnection *connection)
670 {
671   /* This kills the connection without expecting it to affect
672    * the rest of the bus.
673    */
674   _dbus_verbose ("Unchecked kill of connection %p\n", connection);
675 
676   dbus_connection_ref (connection);
677   dbus_connection_close (connection);
678   /* dispatching disconnect handler will unref once */
679   if (bus_connection_dispatch_one_message (connection))
680     _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
681 
682   _dbus_assert (!bus_test_client_listed (connection));
683   dbus_connection_unref (connection);
684 }
685 
686 typedef struct
687 {
688   dbus_bool_t failed;
689 } CheckNoMessagesData;
690 
691 static dbus_bool_t
check_no_messages_foreach(DBusConnection * connection,void * data)692 check_no_messages_foreach (DBusConnection *connection,
693                            void           *data)
694 {
695   CheckNoMessagesData *d = data;
696   DBusMessage *message;
697 
698   message = pop_message_waiting_for_memory (connection);
699   if (message != NULL)
700     {
701       warn_unexpected (connection, message, "no messages");
702 
703       d->failed = TRUE;
704     }
705 
706   if (message)
707     dbus_message_unref (message);
708   return !d->failed;
709 }
710 
711 static dbus_bool_t
check_no_leftovers(BusContext * context)712 check_no_leftovers (BusContext *context)
713 {
714   CheckNoMessagesData nmd;
715 
716   nmd.failed = FALSE;
717   bus_test_clients_foreach (check_no_messages_foreach,
718                             &nmd);
719 
720   if (nmd.failed)
721     {
722       _dbus_verbose ("%s: leftover message found\n",
723                      _DBUS_FUNCTION_NAME);
724       return FALSE;
725     }
726   else
727     return TRUE;
728 }
729 
730 /* returns TRUE if the correct thing happens,
731  * but the correct thing may include OOM errors.
732  */
733 static dbus_bool_t
check_hello_message(BusContext * context,DBusConnection * connection)734 check_hello_message (BusContext     *context,
735                      DBusConnection *connection)
736 {
737   DBusMessage *message;
738   DBusMessage *name_message;
739   dbus_uint32_t serial;
740   dbus_bool_t retval;
741   DBusError error;
742   const char *name;
743   const char *acquired;
744 
745   retval = FALSE;
746   dbus_error_init (&error);
747   name = NULL;
748   acquired = NULL;
749   message = NULL;
750   name_message = NULL;
751 
752   _dbus_verbose ("check_hello_message for %p\n", connection);
753 
754   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
755                                           DBUS_PATH_DBUS,
756                                           DBUS_INTERFACE_DBUS,
757                                           "Hello");
758 
759   if (message == NULL)
760     return TRUE;
761 
762   dbus_connection_ref (connection); /* because we may get disconnected */
763 
764   if (!dbus_connection_send (connection, message, &serial))
765     {
766       dbus_message_unref (message);
767       dbus_connection_unref (connection);
768       return TRUE;
769     }
770 
771   _dbus_assert (dbus_message_has_signature (message, ""));
772 
773   dbus_message_unref (message);
774   message = NULL;
775 
776   if (!dbus_connection_get_is_connected (connection))
777     {
778       _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
779 
780       dbus_connection_unref (connection);
781 
782       return TRUE;
783     }
784 
785   /* send our message */
786   bus_test_run_clients_loop (SEND_PENDING (connection));
787 
788   if (!dbus_connection_get_is_connected (connection))
789     {
790       _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
791 
792       dbus_connection_unref (connection);
793 
794       return TRUE;
795     }
796 
797   block_connection_until_message_from_bus (context, connection, "reply to Hello");
798 
799   if (!dbus_connection_get_is_connected (connection))
800     {
801       _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
802 
803       dbus_connection_unref (connection);
804 
805       return TRUE;
806     }
807 
808   dbus_connection_unref (connection);
809 
810   message = pop_message_waiting_for_memory (connection);
811   if (message == NULL)
812     {
813       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
814                   "Hello", serial, connection);
815       goto out;
816     }
817 
818   verbose_message_received (connection, message);
819 
820   if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
821     {
822       _dbus_warn ("Message has wrong sender %s\n",
823                   dbus_message_get_sender (message) ?
824                   dbus_message_get_sender (message) : "(none)");
825       goto out;
826     }
827 
828   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
829     {
830       if (dbus_message_is_error (message,
831                                  DBUS_ERROR_NO_MEMORY))
832         {
833           ; /* good, this is a valid response */
834         }
835       else
836         {
837           warn_unexpected (connection, message, "not this error");
838 
839           goto out;
840         }
841     }
842   else
843     {
844       CheckServiceOwnerChangedData socd;
845 
846       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
847         {
848           ; /* good, expected */
849         }
850       else
851         {
852           warn_unexpected (connection, message, "method return for Hello");
853 
854           goto out;
855         }
856 
857     retry_get_hello_name:
858       if (!dbus_message_get_args (message, &error,
859                                   DBUS_TYPE_STRING, &name,
860                                   DBUS_TYPE_INVALID))
861         {
862           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
863             {
864               _dbus_verbose ("no memory to get service name arg from hello\n");
865               dbus_error_free (&error);
866               _dbus_wait_for_memory ();
867               goto retry_get_hello_name;
868             }
869           else
870             {
871               _dbus_assert (dbus_error_is_set (&error));
872               _dbus_warn ("Did not get the expected single string argument to hello\n");
873               goto out;
874             }
875         }
876 
877       _dbus_verbose ("Got hello name: %s\n", name);
878 
879       while (!dbus_bus_set_unique_name (connection, name))
880         _dbus_wait_for_memory ();
881 
882       socd.expected_kind = SERVICE_CREATED;
883       socd.expected_service_name = name;
884       socd.failed = FALSE;
885       socd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
886       bus_test_clients_foreach (check_service_owner_changed_foreach,
887                                 &socd);
888 
889       if (socd.failed)
890         goto out;
891 
892       name_message = message;
893       /* Client should also have gotten ServiceAcquired */
894 
895       message = pop_message_waiting_for_memory (connection);
896       if (message == NULL)
897         {
898           _dbus_warn ("Expecting %s, got nothing\n",
899                       "NameAcquired");
900           goto out;
901         }
902       if (! dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
903                                     "NameAcquired"))
904         {
905           _dbus_warn ("Expecting %s, got smthg else\n",
906                       "NameAcquired");
907           goto out;
908         }
909 
910     retry_get_acquired_name:
911       if (!dbus_message_get_args (message, &error,
912                                   DBUS_TYPE_STRING, &acquired,
913                                   DBUS_TYPE_INVALID))
914         {
915           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
916             {
917               _dbus_verbose ("no memory to get service name arg from acquired\n");
918               dbus_error_free (&error);
919               _dbus_wait_for_memory ();
920               goto retry_get_acquired_name;
921             }
922           else
923             {
924               _dbus_assert (dbus_error_is_set (&error));
925               _dbus_warn ("Did not get the expected single string argument to ServiceAcquired\n");
926               goto out;
927             }
928         }
929 
930       _dbus_verbose ("Got acquired name: %s\n", acquired);
931 
932       if (strcmp (acquired, name) != 0)
933         {
934           _dbus_warn ("Acquired name is %s but expected %s\n",
935                       acquired, name);
936           goto out;
937         }
938       acquired = NULL;
939     }
940 
941   if (!check_no_leftovers (context))
942     goto out;
943 
944   retval = TRUE;
945 
946  out:
947   _dbus_verbose ("ending %s retval = %d\n", _DBUS_FUNCTION_NAME, retval);
948 
949   dbus_error_free (&error);
950 
951   if (message)
952     dbus_message_unref (message);
953 
954   if (name_message)
955     dbus_message_unref (name_message);
956 
957   return retval;
958 }
959 
960 /* returns TRUE if the correct thing happens,
961  * but the correct thing may include OOM errors.
962  */
963 static dbus_bool_t
check_double_hello_message(BusContext * context,DBusConnection * connection)964 check_double_hello_message (BusContext     *context,
965                             DBusConnection *connection)
966 {
967   DBusMessage *message;
968   dbus_uint32_t serial;
969   dbus_bool_t retval;
970   DBusError error;
971 
972   retval = FALSE;
973   dbus_error_init (&error);
974   message = NULL;
975 
976   _dbus_verbose ("check_double_hello_message for %p\n", connection);
977 
978   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
979                                           DBUS_PATH_DBUS,
980                                           DBUS_INTERFACE_DBUS,
981                                           "Hello");
982 
983   if (message == NULL)
984     return TRUE;
985 
986   if (!dbus_connection_send (connection, message, &serial))
987     {
988       dbus_message_unref (message);
989       return TRUE;
990     }
991 
992   dbus_message_unref (message);
993   message = NULL;
994 
995   /* send our message */
996   bus_test_run_clients_loop (SEND_PENDING (connection));
997 
998   dbus_connection_ref (connection); /* because we may get disconnected */
999   block_connection_until_message_from_bus (context, connection, "reply to Hello");
1000 
1001   if (!dbus_connection_get_is_connected (connection))
1002     {
1003       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
1004 
1005       dbus_connection_unref (connection);
1006 
1007       return TRUE;
1008     }
1009 
1010   dbus_connection_unref (connection);
1011 
1012   message = pop_message_waiting_for_memory (connection);
1013   if (message == NULL)
1014     {
1015       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1016                   "Hello", serial, connection);
1017       goto out;
1018     }
1019 
1020   verbose_message_received (connection, message);
1021 
1022   if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1023     {
1024       _dbus_warn ("Message has wrong sender %s\n",
1025                   dbus_message_get_sender (message) ?
1026                   dbus_message_get_sender (message) : "(none)");
1027       goto out;
1028     }
1029 
1030   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
1031     {
1032       warn_unexpected (connection, message, "method return for Hello");
1033       goto out;
1034     }
1035 
1036   if (!check_no_leftovers (context))
1037     goto out;
1038 
1039   retval = TRUE;
1040 
1041  out:
1042   dbus_error_free (&error);
1043 
1044   if (message)
1045     dbus_message_unref (message);
1046 
1047   return retval;
1048 }
1049 
1050 /* returns TRUE if the correct thing happens,
1051  * but the correct thing may include OOM errors.
1052  */
1053 static dbus_bool_t
check_get_connection_unix_user(BusContext * context,DBusConnection * connection)1054 check_get_connection_unix_user (BusContext     *context,
1055                                 DBusConnection *connection)
1056 {
1057   DBusMessage *message;
1058   dbus_uint32_t serial;
1059   dbus_bool_t retval;
1060   DBusError error;
1061   const char *base_service_name;
1062   dbus_uint32_t uid;
1063 
1064   retval = FALSE;
1065   dbus_error_init (&error);
1066   message = NULL;
1067 
1068   _dbus_verbose ("check_get_connection_unix_user for %p\n", connection);
1069 
1070   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1071                                           DBUS_PATH_DBUS,
1072                                           DBUS_INTERFACE_DBUS,
1073                                           "GetConnectionUnixUser");
1074 
1075   if (message == NULL)
1076     return TRUE;
1077 
1078   base_service_name = dbus_bus_get_unique_name (connection);
1079 
1080   if (!dbus_message_append_args (message,
1081                                  DBUS_TYPE_STRING, &base_service_name,
1082                                  DBUS_TYPE_INVALID))
1083     {
1084       dbus_message_unref (message);
1085       return TRUE;
1086     }
1087 
1088   if (!dbus_connection_send (connection, message, &serial))
1089     {
1090       dbus_message_unref (message);
1091       return TRUE;
1092     }
1093 
1094   /* send our message */
1095   bus_test_run_clients_loop (SEND_PENDING (connection));
1096 
1097   dbus_message_unref (message);
1098   message = NULL;
1099 
1100   dbus_connection_ref (connection); /* because we may get disconnected */
1101   block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixUser");
1102 
1103   if (!dbus_connection_get_is_connected (connection))
1104     {
1105       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
1106 
1107       dbus_connection_unref (connection);
1108 
1109       return TRUE;
1110     }
1111 
1112   dbus_connection_unref (connection);
1113 
1114   message = pop_message_waiting_for_memory (connection);
1115   if (message == NULL)
1116     {
1117       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1118                   "GetConnectionUnixUser", serial, connection);
1119       goto out;
1120     }
1121 
1122   verbose_message_received (connection, message);
1123 
1124   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1125     {
1126       if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
1127         {
1128           ; /* good, this is a valid response */
1129         }
1130       else
1131         {
1132           warn_unexpected (connection, message, "not this error");
1133 
1134           goto out;
1135         }
1136     }
1137   else
1138     {
1139       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1140         {
1141           ; /* good, expected */
1142         }
1143       else
1144         {
1145           warn_unexpected (connection, message,
1146                            "method_return for GetConnectionUnixUser");
1147 
1148           goto out;
1149         }
1150 
1151     retry_get_property:
1152 
1153       if (!dbus_message_get_args (message, &error,
1154                                   DBUS_TYPE_UINT32, &uid,
1155                                   DBUS_TYPE_INVALID))
1156         {
1157           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1158             {
1159               _dbus_verbose ("no memory to get uid by GetConnectionUnixUser\n");
1160               dbus_error_free (&error);
1161               _dbus_wait_for_memory ();
1162               goto retry_get_property;
1163             }
1164           else
1165             {
1166               _dbus_assert (dbus_error_is_set (&error));
1167               _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixUser\n");
1168               goto out;
1169             }
1170         }
1171     }
1172 
1173   if (!check_no_leftovers (context))
1174     goto out;
1175 
1176   retval = TRUE;
1177 
1178  out:
1179   dbus_error_free (&error);
1180 
1181   if (message)
1182     dbus_message_unref (message);
1183 
1184   return retval;
1185 }
1186 
1187 /* returns TRUE if the correct thing happens,
1188  * but the correct thing may include OOM errors.
1189  */
1190 static dbus_bool_t
check_get_connection_unix_process_id(BusContext * context,DBusConnection * connection)1191 check_get_connection_unix_process_id (BusContext     *context,
1192                                       DBusConnection *connection)
1193 {
1194   DBusMessage *message;
1195   dbus_uint32_t serial;
1196   dbus_bool_t retval;
1197   DBusError error;
1198   const char *base_service_name;
1199   dbus_uint32_t pid;
1200 
1201   retval = FALSE;
1202   dbus_error_init (&error);
1203   message = NULL;
1204 
1205   _dbus_verbose ("check_get_connection_unix_process_id for %p\n", connection);
1206 
1207   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1208                                           DBUS_PATH_DBUS,
1209                                           DBUS_INTERFACE_DBUS,
1210                                           "GetConnectionUnixProcessID");
1211 
1212   if (message == NULL)
1213     return TRUE;
1214 
1215   base_service_name = dbus_bus_get_unique_name (connection);
1216 
1217   if (!dbus_message_append_args (message,
1218                                  DBUS_TYPE_STRING, &base_service_name,
1219                                  DBUS_TYPE_INVALID))
1220     {
1221       dbus_message_unref (message);
1222       return TRUE;
1223     }
1224 
1225   if (!dbus_connection_send (connection, message, &serial))
1226     {
1227       dbus_message_unref (message);
1228       return TRUE;
1229     }
1230 
1231   /* send our message */
1232   bus_test_run_clients_loop (SEND_PENDING (connection));
1233 
1234   dbus_message_unref (message);
1235   message = NULL;
1236 
1237   dbus_connection_ref (connection); /* because we may get disconnected */
1238   block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixProcessID");
1239 
1240   if (!dbus_connection_get_is_connected (connection))
1241     {
1242       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
1243 
1244       dbus_connection_unref (connection);
1245 
1246       return TRUE;
1247     }
1248 
1249   dbus_connection_unref (connection);
1250 
1251   message = pop_message_waiting_for_memory (connection);
1252   if (message == NULL)
1253     {
1254       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1255                   "GetConnectionUnixProcessID", serial, connection);
1256       goto out;
1257     }
1258 
1259   verbose_message_received (connection, message);
1260 
1261   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1262     {
1263       if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
1264         {
1265           ; /* good, this is a valid response */
1266         }
1267       else
1268         {
1269           warn_unexpected (connection, message, "not this error");
1270 
1271           goto out;
1272         }
1273     }
1274   else
1275     {
1276       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1277         {
1278           ; /* good, expected */
1279         }
1280       else
1281         {
1282           warn_unexpected (connection, message,
1283                            "method_return for GetConnectionUnixProcessID");
1284 
1285           goto out;
1286         }
1287 
1288     retry_get_property:
1289 
1290       if (!dbus_message_get_args (message, &error,
1291                                   DBUS_TYPE_UINT32, &pid,
1292                                   DBUS_TYPE_INVALID))
1293         {
1294           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1295             {
1296               _dbus_verbose ("no memory to get pid by GetConnectionUnixProcessID\n");
1297               dbus_error_free (&error);
1298               _dbus_wait_for_memory ();
1299               goto retry_get_property;
1300             }
1301           else
1302             {
1303               _dbus_assert (dbus_error_is_set (&error));
1304               _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixProcessID\n");
1305               goto out;
1306             }
1307         } else {
1308 
1309           /* test if returned pid is the same as our own pid
1310            *
1311            * @todo It would probably be good to restructure the tests
1312            *       in a way so our parent is the bus that we're testing
1313            *       cause then we can test that the pid returned matches
1314            *       getppid()
1315            */
1316           if (pid != (dbus_uint32_t) _dbus_getpid ())
1317             {
1318               _dbus_assert (dbus_error_is_set (&error));
1319               _dbus_warn ("Result from GetConnectionUnixProcessID is not our own pid\n");
1320               goto out;
1321             }
1322         }
1323     }
1324 
1325   if (!check_no_leftovers (context))
1326     goto out;
1327 
1328   retval = TRUE;
1329 
1330  out:
1331   dbus_error_free (&error);
1332 
1333   if (message)
1334     dbus_message_unref (message);
1335 
1336   return retval;
1337 }
1338 
1339 /* returns TRUE if the correct thing happens,
1340  * but the correct thing may include OOM errors.
1341  */
1342 static dbus_bool_t
check_add_match_all(BusContext * context,DBusConnection * connection)1343 check_add_match_all (BusContext     *context,
1344                      DBusConnection *connection)
1345 {
1346   DBusMessage *message;
1347   dbus_bool_t retval;
1348   dbus_uint32_t serial;
1349   DBusError error;
1350   const char *empty = "";
1351 
1352   retval = FALSE;
1353   dbus_error_init (&error);
1354   message = NULL;
1355 
1356   _dbus_verbose ("check_add_match_all for %p\n", connection);
1357 
1358   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1359                                           DBUS_PATH_DBUS,
1360                                           DBUS_INTERFACE_DBUS,
1361                                           "AddMatch");
1362 
1363   if (message == NULL)
1364     return TRUE;
1365 
1366   /* empty string match rule matches everything */
1367   if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &empty,
1368                                  DBUS_TYPE_INVALID))
1369     {
1370       dbus_message_unref (message);
1371       return TRUE;
1372     }
1373 
1374   if (!dbus_connection_send (connection, message, &serial))
1375     {
1376       dbus_message_unref (message);
1377       return TRUE;
1378     }
1379 
1380   dbus_message_unref (message);
1381   message = NULL;
1382 
1383   dbus_connection_ref (connection); /* because we may get disconnected */
1384 
1385   /* send our message */
1386   bus_test_run_clients_loop (SEND_PENDING (connection));
1387 
1388   if (!dbus_connection_get_is_connected (connection))
1389     {
1390       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
1391 
1392       dbus_connection_unref (connection);
1393 
1394       return TRUE;
1395     }
1396 
1397   block_connection_until_message_from_bus (context, connection, "reply to AddMatch");
1398 
1399   if (!dbus_connection_get_is_connected (connection))
1400     {
1401       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
1402 
1403       dbus_connection_unref (connection);
1404 
1405       return TRUE;
1406     }
1407 
1408   dbus_connection_unref (connection);
1409 
1410   message = pop_message_waiting_for_memory (connection);
1411   if (message == NULL)
1412     {
1413       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1414                   "AddMatch", serial, connection);
1415       goto out;
1416     }
1417 
1418   verbose_message_received (connection, message);
1419 
1420   if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1421     {
1422       _dbus_warn ("Message has wrong sender %s\n",
1423                   dbus_message_get_sender (message) ?
1424                   dbus_message_get_sender (message) : "(none)");
1425       goto out;
1426     }
1427 
1428   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1429     {
1430       if (dbus_message_is_error (message,
1431                                  DBUS_ERROR_NO_MEMORY))
1432         {
1433           ; /* good, this is a valid response */
1434         }
1435       else
1436         {
1437           warn_unexpected (connection, message, "not this error");
1438 
1439           goto out;
1440         }
1441     }
1442   else
1443     {
1444       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1445         {
1446           ; /* good, expected */
1447           _dbus_assert (dbus_message_get_reply_serial (message) == serial);
1448         }
1449       else
1450         {
1451           warn_unexpected (connection, message, "method return for AddMatch");
1452 
1453           goto out;
1454         }
1455     }
1456 
1457   if (!check_no_leftovers (context))
1458     goto out;
1459 
1460   retval = TRUE;
1461 
1462  out:
1463   dbus_error_free (&error);
1464 
1465   if (message)
1466     dbus_message_unref (message);
1467 
1468   return retval;
1469 }
1470 
1471 /* returns TRUE if the correct thing happens,
1472  * but the correct thing may include OOM errors.
1473  */
1474 static dbus_bool_t
check_hello_connection(BusContext * context)1475 check_hello_connection (BusContext *context)
1476 {
1477   DBusConnection *connection;
1478   DBusError error;
1479 
1480   dbus_error_init (&error);
1481 
1482   connection = dbus_connection_open_private ("debug-pipe:name=test-server", &error);
1483   if (connection == NULL)
1484     {
1485       _DBUS_ASSERT_ERROR_IS_SET (&error);
1486       dbus_error_free (&error);
1487       return TRUE;
1488     }
1489 
1490   if (!bus_setup_debug_client (connection))
1491     {
1492       dbus_connection_close (connection);
1493       dbus_connection_unref (connection);
1494       return TRUE;
1495     }
1496 
1497   spin_connection_until_authenticated (context, connection);
1498 
1499   if (!check_hello_message (context, connection))
1500     return FALSE;
1501 
1502   if (dbus_bus_get_unique_name (connection) == NULL)
1503     {
1504       /* We didn't successfully register, so we can't
1505        * do the usual kill_client_connection() checks
1506        */
1507       kill_client_connection_unchecked (connection);
1508     }
1509   else
1510     {
1511       if (!check_add_match_all (context, connection))
1512         return FALSE;
1513 
1514       kill_client_connection (context, connection);
1515     }
1516 
1517   return TRUE;
1518 }
1519 
1520 #define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
1521 
1522 /* returns TRUE if the correct thing happens,
1523  * but the correct thing may include OOM errors.
1524  */
1525 static dbus_bool_t
check_nonexistent_service_no_auto_start(BusContext * context,DBusConnection * connection)1526 check_nonexistent_service_no_auto_start (BusContext     *context,
1527                                          DBusConnection *connection)
1528 {
1529   DBusMessage *message;
1530   dbus_uint32_t serial;
1531   dbus_bool_t retval;
1532   const char *nonexistent = NONEXISTENT_SERVICE_NAME;
1533   dbus_uint32_t flags;
1534 
1535   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1536                                           DBUS_PATH_DBUS,
1537                                           DBUS_INTERFACE_DBUS,
1538                                           "StartServiceByName");
1539 
1540   if (message == NULL)
1541     return TRUE;
1542 
1543   dbus_message_set_auto_start (message, FALSE);
1544 
1545   flags = 0;
1546   if (!dbus_message_append_args (message,
1547                                  DBUS_TYPE_STRING, &nonexistent,
1548                                  DBUS_TYPE_UINT32, &flags,
1549                                  DBUS_TYPE_INVALID))
1550     {
1551       dbus_message_unref (message);
1552       return TRUE;
1553     }
1554 
1555   if (!dbus_connection_send (connection, message, &serial))
1556     {
1557       dbus_message_unref (message);
1558       return TRUE;
1559     }
1560 
1561   dbus_message_unref (message);
1562   message = NULL;
1563 
1564   bus_test_run_everything (context);
1565   block_connection_until_message_from_bus (context, connection, "reply to ActivateService on nonexistent");
1566   bus_test_run_everything (context);
1567 
1568   if (!dbus_connection_get_is_connected (connection))
1569     {
1570       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
1571       return TRUE;
1572     }
1573 
1574   retval = FALSE;
1575 
1576   message = pop_message_waiting_for_memory (connection);
1577   if (message == NULL)
1578     {
1579       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1580                   "StartServiceByName", serial, connection);
1581       goto out;
1582     }
1583 
1584   verbose_message_received (connection, message);
1585 
1586   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1587     {
1588       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1589         {
1590           _dbus_warn ("Message has wrong sender %s\n",
1591                       dbus_message_get_sender (message) ?
1592                       dbus_message_get_sender (message) : "(none)");
1593           goto out;
1594         }
1595 
1596       if (dbus_message_is_error (message,
1597                                  DBUS_ERROR_NO_MEMORY))
1598         {
1599           ; /* good, this is a valid response */
1600         }
1601       else if (dbus_message_is_error (message,
1602                                       DBUS_ERROR_SERVICE_UNKNOWN))
1603         {
1604           ; /* good, this is expected also */
1605         }
1606       else
1607         {
1608           warn_unexpected (connection, message, "not this error");
1609           goto out;
1610         }
1611     }
1612   else
1613     {
1614       _dbus_warn ("Did not expect to successfully activate %s\n",
1615                   NONEXISTENT_SERVICE_NAME);
1616       goto out;
1617     }
1618 
1619   retval = TRUE;
1620 
1621  out:
1622   if (message)
1623     dbus_message_unref (message);
1624 
1625   return retval;
1626 }
1627 
1628 /* returns TRUE if the correct thing happens,
1629  * but the correct thing may include OOM errors.
1630  */
1631 static dbus_bool_t
check_nonexistent_service_auto_start(BusContext * context,DBusConnection * connection)1632 check_nonexistent_service_auto_start (BusContext     *context,
1633                                       DBusConnection *connection)
1634 {
1635   DBusMessage *message;
1636   dbus_uint32_t serial;
1637   dbus_bool_t retval;
1638 
1639   message = dbus_message_new_method_call (NONEXISTENT_SERVICE_NAME,
1640                                           "/org/freedesktop/TestSuite",
1641                                           "org.freedesktop.TestSuite",
1642                                           "Echo");
1643 
1644   if (message == NULL)
1645     return TRUE;
1646 
1647   if (!dbus_connection_send (connection, message, &serial))
1648     {
1649       dbus_message_unref (message);
1650       return TRUE;
1651     }
1652 
1653   dbus_message_unref (message);
1654   message = NULL;
1655 
1656   bus_test_run_everything (context);
1657   block_connection_until_message_from_bus (context, connection, "reply to Echo");
1658   bus_test_run_everything (context);
1659 
1660   if (!dbus_connection_get_is_connected (connection))
1661     {
1662       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
1663       return TRUE;
1664     }
1665 
1666   retval = FALSE;
1667 
1668   message = pop_message_waiting_for_memory (connection);
1669 
1670   if (message == NULL)
1671     {
1672       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1673                   "Echo message (auto activation)", serial, connection);
1674       goto out;
1675     }
1676 
1677   verbose_message_received (connection, message);
1678 
1679   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1680     {
1681       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1682         {
1683           _dbus_warn ("Message has wrong sender %s\n",
1684                       dbus_message_get_sender (message) ?
1685                       dbus_message_get_sender (message) : "(none)");
1686           goto out;
1687         }
1688 
1689       if (dbus_message_is_error (message,
1690                                  DBUS_ERROR_NO_MEMORY))
1691         {
1692           ; /* good, this is a valid response */
1693         }
1694       else if (dbus_message_is_error (message,
1695                                       DBUS_ERROR_SERVICE_UNKNOWN))
1696         {
1697           ; /* good, this is expected also */
1698         }
1699       else
1700         {
1701           warn_unexpected (connection, message, "not this error");
1702           goto out;
1703         }
1704     }
1705   else
1706     {
1707       _dbus_warn ("Did not expect to successfully activate %s\n",
1708                   NONEXISTENT_SERVICE_NAME);
1709       goto out;
1710     }
1711 
1712   retval = TRUE;
1713 
1714  out:
1715   if (message)
1716     dbus_message_unref (message);
1717 
1718   return retval;
1719 }
1720 
1721 static dbus_bool_t
check_base_service_activated(BusContext * context,DBusConnection * connection,DBusMessage * initial_message,const char ** base_service_p)1722 check_base_service_activated (BusContext     *context,
1723                               DBusConnection *connection,
1724                               DBusMessage    *initial_message,
1725                               const char    **base_service_p)
1726 {
1727   DBusMessage *message;
1728   dbus_bool_t retval;
1729   DBusError error;
1730   const char *base_service, *base_service_from_bus, *old_owner;
1731 
1732   retval = FALSE;
1733 
1734   dbus_error_init (&error);
1735   base_service = NULL;
1736   old_owner = NULL;
1737   base_service_from_bus = NULL;
1738 
1739   message = initial_message;
1740   dbus_message_ref (message);
1741 
1742   if (dbus_message_is_signal (message,
1743                               DBUS_INTERFACE_DBUS,
1744                               "NameOwnerChanged"))
1745     {
1746       CheckServiceOwnerChangedData socd;
1747 
1748     reget_service_name_arg:
1749       base_service = NULL;
1750       old_owner = NULL;
1751       base_service_from_bus = NULL;
1752 
1753       if (!dbus_message_get_args (message, &error,
1754                                   DBUS_TYPE_STRING, &base_service,
1755                                   DBUS_TYPE_STRING, &old_owner,
1756                                   DBUS_TYPE_STRING, &base_service_from_bus,
1757                                   DBUS_TYPE_INVALID))
1758         {
1759           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1760             {
1761               dbus_error_free (&error);
1762               _dbus_wait_for_memory ();
1763               goto reget_service_name_arg;
1764             }
1765           else
1766             {
1767               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1768                           "NameOwnerChanged (creation)",
1769                           error.message);
1770               goto out;
1771             }
1772         }
1773 
1774       if (*base_service != ':')
1775         {
1776           _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
1777                       base_service);
1778           goto out;
1779         }
1780 
1781       if (strcmp (base_service, base_service_from_bus) != 0)
1782         {
1783           _dbus_warn ("Expected base service activation, got \"%s\" instead with owner \"%s\"\n",
1784                       base_service, base_service_from_bus);
1785           goto out;
1786         }
1787 
1788       if (old_owner[0])
1789         {
1790           _dbus_warn ("Received an old_owner argument during base service activation, \"%s\"\n",
1791                       old_owner);
1792           goto out;
1793         }
1794 
1795       socd.expected_kind = SERVICE_CREATED;
1796       socd.expected_service_name = base_service;
1797       socd.failed = FALSE;
1798       socd.skip_connection = connection;
1799       bus_test_clients_foreach (check_service_owner_changed_foreach,
1800                                 &socd);
1801 
1802       if (socd.failed)
1803         goto out;
1804     }
1805   else
1806     {
1807       warn_unexpected (connection, message, "NameOwnerChanged (creation) for base service");
1808 
1809       goto out;
1810     }
1811 
1812   if (base_service_p)
1813     *base_service_p = base_service;
1814 
1815   retval = TRUE;
1816 
1817  out:
1818   if (message)
1819     dbus_message_unref (message);
1820   dbus_error_free (&error);
1821 
1822   return retval;
1823 }
1824 
1825 static dbus_bool_t
check_service_activated(BusContext * context,DBusConnection * connection,const char * activated_name,const char * base_service_name,DBusMessage * initial_message)1826 check_service_activated (BusContext     *context,
1827                          DBusConnection *connection,
1828                          const char     *activated_name,
1829                          const char     *base_service_name,
1830                          DBusMessage    *initial_message)
1831 {
1832   DBusMessage *message;
1833   dbus_bool_t retval;
1834   DBusError error;
1835   dbus_uint32_t activation_result;
1836 
1837   retval = FALSE;
1838 
1839   dbus_error_init (&error);
1840 
1841   message = initial_message;
1842   dbus_message_ref (message);
1843 
1844   if (dbus_message_is_signal (message,
1845                               DBUS_INTERFACE_DBUS,
1846                               "NameOwnerChanged"))
1847     {
1848       CheckServiceOwnerChangedData socd;
1849       const char *service_name, *base_service_from_bus, *old_owner;
1850 
1851     reget_service_name_arg:
1852       service_name = NULL;
1853       old_owner = NULL;
1854       base_service_from_bus = NULL;
1855 
1856       if (!dbus_message_get_args (message, &error,
1857                                   DBUS_TYPE_STRING, &service_name,
1858                                    DBUS_TYPE_STRING, &old_owner,
1859                                   DBUS_TYPE_STRING, &base_service_from_bus,
1860                                   DBUS_TYPE_INVALID))
1861         {
1862           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1863             {
1864               dbus_error_free (&error);
1865               _dbus_wait_for_memory ();
1866               goto reget_service_name_arg;
1867             }
1868           else
1869             {
1870               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1871                           "NameOwnerChanged (creation)",
1872                           error.message);
1873               goto out;
1874             }
1875         }
1876 
1877       if (strcmp (service_name, activated_name) != 0)
1878         {
1879           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
1880                       activated_name, service_name);
1881           goto out;
1882         }
1883 
1884       if (strcmp (base_service_name, base_service_from_bus) != 0)
1885         {
1886           _dbus_warn ("NameOwnerChanged reports wrong base service: %s owner, expected %s instead\n",
1887                       base_service_from_bus, base_service_name);
1888           goto out;
1889         }
1890 
1891       if (old_owner[0])
1892         {
1893           _dbus_warn ("expected a %s, got a %s\n",
1894                       "NameOwnerChanged (creation)",
1895                       "NameOwnerChanged (change)");
1896           goto out;
1897         }
1898 
1899       socd.expected_kind = SERVICE_CREATED;
1900       socd.skip_connection = connection;
1901       socd.failed = FALSE;
1902       socd.expected_service_name = service_name;
1903       bus_test_clients_foreach (check_service_owner_changed_foreach,
1904                                 &socd);
1905 
1906       if (socd.failed)
1907         goto out;
1908 
1909       dbus_message_unref (message);
1910       service_name = NULL;
1911       old_owner = NULL;
1912       base_service_from_bus = NULL;
1913 
1914       message = pop_message_waiting_for_memory (connection);
1915       if (message == NULL)
1916         {
1917           _dbus_warn ("Expected a reply to %s, got nothing\n",
1918                       "StartServiceByName");
1919           goto out;
1920         }
1921     }
1922   else
1923     {
1924       warn_unexpected (connection, message, "NameOwnerChanged for the activated name");
1925 
1926       goto out;
1927     }
1928 
1929   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
1930     {
1931       warn_unexpected (connection, message, "reply to StartServiceByName");
1932 
1933       goto out;
1934     }
1935 
1936   activation_result = 0;
1937   if (!dbus_message_get_args (message, &error,
1938                               DBUS_TYPE_UINT32, &activation_result,
1939                               DBUS_TYPE_INVALID))
1940     {
1941       if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1942         {
1943           _dbus_warn ("Did not have activation result first argument to %s: %s\n",
1944                       "StartServiceByName", error.message);
1945           goto out;
1946         }
1947 
1948       dbus_error_free (&error);
1949     }
1950   else
1951     {
1952       if (activation_result == DBUS_START_REPLY_SUCCESS)
1953         ; /* Good */
1954       else if (activation_result == DBUS_START_REPLY_ALREADY_RUNNING)
1955         ; /* Good also */
1956       else
1957         {
1958           _dbus_warn ("Activation result was %u, no good.\n",
1959                       activation_result);
1960           goto out;
1961         }
1962     }
1963 
1964   dbus_message_unref (message);
1965   message = NULL;
1966 
1967   if (!check_no_leftovers (context))
1968     {
1969       _dbus_warn ("Messages were left over after verifying existent activation results\n");
1970       goto out;
1971     }
1972 
1973   retval = TRUE;
1974 
1975  out:
1976   if (message)
1977     dbus_message_unref (message);
1978   dbus_error_free (&error);
1979 
1980   return retval;
1981 }
1982 
1983 static dbus_bool_t
check_service_auto_activated(BusContext * context,DBusConnection * connection,const char * activated_name,const char * base_service_name,DBusMessage * initial_message)1984 check_service_auto_activated (BusContext     *context,
1985                               DBusConnection *connection,
1986                               const char     *activated_name,
1987                               const char     *base_service_name,
1988                               DBusMessage    *initial_message)
1989 {
1990   DBusMessage *message;
1991   dbus_bool_t retval;
1992   DBusError error;
1993 
1994   retval = FALSE;
1995 
1996   dbus_error_init (&error);
1997 
1998   message = initial_message;
1999   dbus_message_ref (message);
2000 
2001   if (dbus_message_is_signal (message,
2002                               DBUS_INTERFACE_DBUS,
2003                               "NameOwnerChanged"))
2004     {
2005       const char *service_name;
2006       CheckServiceOwnerChangedData socd;
2007 
2008     reget_service_name_arg:
2009       if (!dbus_message_get_args (message, &error,
2010                                   DBUS_TYPE_STRING, &service_name,
2011                                   DBUS_TYPE_INVALID))
2012         {
2013           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2014             {
2015               dbus_error_free (&error);
2016               _dbus_wait_for_memory ();
2017               goto reget_service_name_arg;
2018             }
2019           else
2020             {
2021               _dbus_warn ("Message %s doesn't have a service name: %s\n",
2022                           "NameOwnerChanged",
2023                           error.message);
2024               dbus_error_free (&error);
2025               goto out;
2026             }
2027         }
2028 
2029       if (strcmp (service_name, activated_name) != 0)
2030         {
2031           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
2032                       activated_name, service_name);
2033           goto out;
2034         }
2035 
2036       socd.expected_kind = SERVICE_CREATED;
2037       socd.expected_service_name = service_name;
2038       socd.failed = FALSE;
2039       socd.skip_connection = connection;
2040       bus_test_clients_foreach (check_service_owner_changed_foreach,
2041                                 &socd);
2042 
2043       if (socd.failed)
2044         goto out;
2045 
2046       /* Note that this differs from regular activation in that we don't get a
2047        * reply to ActivateService here.
2048        */
2049 
2050       dbus_message_unref (message);
2051       message = NULL;
2052       service_name = NULL;
2053     }
2054   else
2055     {
2056       warn_unexpected (connection, message, "NameOwnerChanged for the activated name");
2057 
2058       goto out;
2059     }
2060 
2061   retval = TRUE;
2062 
2063  out:
2064   if (message)
2065     dbus_message_unref (message);
2066 
2067   return retval;
2068 }
2069 
2070 static dbus_bool_t
check_service_deactivated(BusContext * context,DBusConnection * connection,const char * activated_name,const char * base_service)2071 check_service_deactivated (BusContext     *context,
2072                            DBusConnection *connection,
2073                            const char     *activated_name,
2074                            const char     *base_service)
2075 {
2076   dbus_bool_t retval;
2077   CheckServiceOwnerChangedData socd;
2078 
2079   retval = FALSE;
2080 
2081   /* Now we are expecting ServiceOwnerChanged (deletion) messages for the base
2082    * service and the activated_name.  The base service
2083    * notification is required to come last.
2084    */
2085   socd.expected_kind = SERVICE_DELETED;
2086   socd.expected_service_name = activated_name;
2087   socd.failed = FALSE;
2088   socd.skip_connection = NULL;
2089   bus_test_clients_foreach (check_service_owner_changed_foreach,
2090                             &socd);
2091 
2092   if (socd.failed)
2093     goto out;
2094 
2095   socd.expected_kind = SERVICE_DELETED;
2096   socd.expected_service_name = base_service;
2097   socd.failed = FALSE;
2098   socd.skip_connection = NULL;
2099   bus_test_clients_foreach (check_service_owner_changed_foreach,
2100                             &socd);
2101 
2102   if (socd.failed)
2103     goto out;
2104 
2105   retval = TRUE;
2106 
2107  out:
2108   return retval;
2109 }
2110 
2111 static dbus_bool_t
check_send_exit_to_service(BusContext * context,DBusConnection * connection,const char * service_name,const char * base_service)2112 check_send_exit_to_service (BusContext     *context,
2113                             DBusConnection *connection,
2114                             const char     *service_name,
2115                             const char     *base_service)
2116 {
2117   dbus_bool_t got_error;
2118   DBusMessage *message;
2119   dbus_uint32_t serial;
2120   dbus_bool_t retval;
2121 
2122   _dbus_verbose ("Sending exit message to the test service\n");
2123 
2124   retval = FALSE;
2125 
2126   /* Kill off the test service by sending it a quit message */
2127   message = dbus_message_new_method_call (service_name,
2128                                           "/org/freedesktop/TestSuite",
2129                                           "org.freedesktop.TestSuite",
2130                                           "Exit");
2131 
2132   if (message == NULL)
2133     {
2134       /* Do this again; we still need the service to exit... */
2135       if (!check_send_exit_to_service (context, connection,
2136                                        service_name, base_service))
2137         goto out;
2138 
2139       return TRUE;
2140     }
2141 
2142   if (!dbus_connection_send (connection, message, &serial))
2143     {
2144       dbus_message_unref (message);
2145 
2146       /* Do this again; we still need the service to exit... */
2147       if (!check_send_exit_to_service (context, connection,
2148                                        service_name, base_service))
2149         goto out;
2150 
2151       return TRUE;
2152     }
2153 
2154   dbus_message_unref (message);
2155   message = NULL;
2156 
2157   /* send message */
2158   bus_test_run_clients_loop (SEND_PENDING (connection));
2159 
2160   /* read it in and write it out to test service */
2161   bus_test_run_bus_loop (context, FALSE);
2162 
2163   /* see if we got an error during message bus dispatching */
2164   bus_test_run_clients_loop (FALSE);
2165   message = borrow_message_waiting_for_memory (connection);
2166   got_error = message != NULL && dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
2167   if (message)
2168     {
2169       dbus_connection_return_message (connection, message);
2170       message = NULL;
2171     }
2172 
2173   if (!got_error)
2174     {
2175       /* If no error, wait for the test service to exit */
2176       block_connection_until_message_from_bus (context, connection, "test service to exit");
2177 
2178       bus_test_run_everything (context);
2179     }
2180 
2181   if (got_error)
2182     {
2183       message = pop_message_waiting_for_memory (connection);
2184       _dbus_assert (message != NULL);
2185 
2186       if (dbus_message_get_reply_serial (message) != serial)
2187         {
2188           warn_unexpected (connection, message,
2189                            "error with the correct reply serial");
2190           goto out;
2191         }
2192 
2193       if (!dbus_message_is_error (message,
2194                                   DBUS_ERROR_NO_MEMORY))
2195         {
2196           warn_unexpected (connection, message,
2197                            "a no memory error from asking test service to exit");
2198           goto out;
2199         }
2200 
2201       _dbus_verbose ("Got error %s when asking test service to exit\n",
2202                      dbus_message_get_error_name (message));
2203 
2204       /* Do this again; we still need the service to exit... */
2205       if (!check_send_exit_to_service (context, connection,
2206                                        service_name, base_service))
2207         goto out;
2208     }
2209   else
2210     {
2211       if (!check_service_deactivated (context, connection,
2212                                       service_name, base_service))
2213         goto out;
2214 
2215       /* Should now have a NoReply error from the Exit() method
2216        * call; it should have come after all the deactivation
2217        * stuff.
2218        */
2219       message = pop_message_waiting_for_memory (connection);
2220 
2221       if (message == NULL)
2222         {
2223           warn_unexpected (connection, NULL,
2224                            "reply to Exit() method call");
2225           goto out;
2226         }
2227       if (!dbus_message_is_error (message,
2228                                   DBUS_ERROR_NO_REPLY))
2229         {
2230           warn_unexpected (connection, message,
2231                            "NoReply error from Exit() method call");
2232           goto out;
2233         }
2234 
2235       if (dbus_message_get_reply_serial (message) != serial)
2236         {
2237           warn_unexpected (connection, message,
2238                            "error with the correct reply serial");
2239           goto out;
2240         }
2241 
2242       _dbus_verbose ("Got error %s after test service exited\n",
2243                      dbus_message_get_error_name (message));
2244 
2245       if (!check_no_leftovers (context))
2246         {
2247           _dbus_warn ("Messages were left over after %s\n",
2248                       _DBUS_FUNCTION_NAME);
2249           goto out;
2250         }
2251     }
2252 
2253   retval = TRUE;
2254 
2255  out:
2256   if (message)
2257     dbus_message_unref (message);
2258 
2259   return retval;
2260 }
2261 
2262 static dbus_bool_t
check_got_error(BusContext * context,DBusConnection * connection,const char * first_error_name,...)2263 check_got_error (BusContext     *context,
2264                  DBusConnection *connection,
2265                  const char     *first_error_name,
2266                  ...)
2267 {
2268   DBusMessage *message;
2269   dbus_bool_t retval;
2270   va_list ap;
2271   dbus_bool_t error_found;
2272   const char *error_name;
2273 
2274   retval = FALSE;
2275 
2276   message = pop_message_waiting_for_memory (connection);
2277   if (message == NULL)
2278     {
2279       _dbus_warn ("Did not get an expected error\n");
2280       goto out;
2281     }
2282 
2283   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
2284     {
2285       warn_unexpected (connection, message, "an error");
2286 
2287       goto out;
2288     }
2289 
2290   error_found = FALSE;
2291 
2292   va_start (ap, first_error_name);
2293   error_name = first_error_name;
2294   while (error_name != NULL)
2295     {
2296       if (dbus_message_is_error (message, error_name))
2297         {
2298           error_found = TRUE;
2299           break;
2300         }
2301       error_name = va_arg (ap, char*);
2302     }
2303   va_end (ap);
2304 
2305   if (!error_found)
2306     {
2307       _dbus_warn ("Expected error %s or other, got %s instead\n",
2308                   first_error_name,
2309                   dbus_message_get_error_name (message));
2310       goto out;
2311     }
2312 
2313   retval = TRUE;
2314 
2315  out:
2316   if (message)
2317     dbus_message_unref (message);
2318 
2319   return retval;
2320 }
2321 
2322 typedef enum
2323 {
2324   GOT_SERVICE_CREATED,
2325   GOT_SERVICE_DELETED,
2326   GOT_ERROR,
2327   GOT_SOMETHING_ELSE
2328 } GotServiceInfo;
2329 
2330 static GotServiceInfo
check_got_service_info(DBusMessage * message)2331 check_got_service_info (DBusMessage *message)
2332 {
2333   GotServiceInfo message_kind;
2334 
2335   if (dbus_message_is_signal (message,
2336                               DBUS_INTERFACE_DBUS,
2337                               "NameOwnerChanged"))
2338     {
2339       DBusError error;
2340       const char *service_name, *old_owner, *new_owner;
2341       dbus_error_init (&error);
2342 
2343     reget_service_info_data:
2344       service_name = NULL;
2345       old_owner = NULL;
2346       new_owner = NULL;
2347 
2348       dbus_message_get_args (message, &error,
2349                              DBUS_TYPE_STRING, &service_name,
2350                              DBUS_TYPE_STRING, &old_owner,
2351                              DBUS_TYPE_STRING, &new_owner,
2352                              DBUS_TYPE_INVALID);
2353       if (dbus_error_is_set (&error))
2354         {
2355           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2356             {
2357               dbus_error_free (&error);
2358               goto reget_service_info_data;
2359             }
2360           else
2361             {
2362               _dbus_warn ("unexpected arguments for NameOwnerChanged message\n");
2363               message_kind = GOT_SOMETHING_ELSE;
2364             }
2365         }
2366       else if (!old_owner[0])
2367         message_kind = GOT_SERVICE_CREATED;
2368       else if (!new_owner[0])
2369         message_kind = GOT_SERVICE_DELETED;
2370       else
2371         message_kind = GOT_SOMETHING_ELSE;
2372 
2373       dbus_error_free (&error);
2374     }
2375   else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2376     message_kind = GOT_ERROR;
2377   else
2378     message_kind = GOT_SOMETHING_ELSE;
2379 
2380   return message_kind;
2381 }
2382 
2383 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
2384 
2385 /* returns TRUE if the correct thing happens,
2386  * but the correct thing may include OOM errors.
2387  */
2388 static dbus_bool_t
check_existent_service_no_auto_start(BusContext * context,DBusConnection * connection)2389 check_existent_service_no_auto_start (BusContext     *context,
2390                                       DBusConnection *connection)
2391 {
2392   DBusMessage *message;
2393   DBusMessage *base_service_message;
2394   const char *base_service;
2395   dbus_uint32_t serial;
2396   dbus_bool_t retval;
2397   const char *existent = EXISTENT_SERVICE_NAME;
2398   dbus_uint32_t flags;
2399 
2400   base_service_message = NULL;
2401 
2402   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
2403                                           DBUS_PATH_DBUS,
2404                                           DBUS_INTERFACE_DBUS,
2405                                           "StartServiceByName");
2406 
2407   if (message == NULL)
2408     return TRUE;
2409 
2410   dbus_message_set_auto_start (message, FALSE);
2411 
2412   flags = 0;
2413   if (!dbus_message_append_args (message,
2414                                  DBUS_TYPE_STRING, &existent,
2415                                  DBUS_TYPE_UINT32, &flags,
2416                                  DBUS_TYPE_INVALID))
2417     {
2418       dbus_message_unref (message);
2419       return TRUE;
2420     }
2421 
2422   if (!dbus_connection_send (connection, message, &serial))
2423     {
2424       dbus_message_unref (message);
2425       return TRUE;
2426     }
2427 
2428   dbus_message_unref (message);
2429   message = NULL;
2430 
2431   bus_test_run_everything (context);
2432 
2433   /* now wait for the message bus to hear back from the activated
2434    * service.
2435    */
2436   block_connection_until_message_from_bus (context, connection, "activated service to connect");
2437 
2438   bus_test_run_everything (context);
2439 
2440   if (!dbus_connection_get_is_connected (connection))
2441     {
2442       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
2443       return TRUE;
2444     }
2445 
2446   retval = FALSE;
2447 
2448   message = pop_message_waiting_for_memory (connection);
2449   if (message == NULL)
2450     {
2451       _dbus_warn ("Did not receive any messages after %s %d on %p\n",
2452                   "StartServiceByName", serial, connection);
2453       goto out;
2454     }
2455 
2456   verbose_message_received (connection, message);
2457   _dbus_verbose ("  (after sending %s)\n", "StartServiceByName");
2458 
2459   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2460     {
2461       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
2462         {
2463           _dbus_warn ("Message has wrong sender %s\n",
2464                       dbus_message_get_sender (message) ?
2465                       dbus_message_get_sender (message) : "(none)");
2466           goto out;
2467         }
2468 
2469       if (dbus_message_is_error (message,
2470                                  DBUS_ERROR_NO_MEMORY))
2471         {
2472           ; /* good, this is a valid response */
2473         }
2474       else if (dbus_message_is_error (message,
2475                                       DBUS_ERROR_SPAWN_CHILD_EXITED) ||
2476                dbus_message_is_error (message,
2477                                       DBUS_ERROR_SPAWN_CHILD_SIGNALED) ||
2478                dbus_message_is_error (message,
2479                                       DBUS_ERROR_SPAWN_EXEC_FAILED))
2480         {
2481           ; /* good, this is expected also */
2482         }
2483       else
2484         {
2485           _dbus_warn ("Did not expect error %s\n",
2486                       dbus_message_get_error_name (message));
2487           goto out;
2488         }
2489     }
2490   else
2491     {
2492       GotServiceInfo message_kind;
2493 
2494       if (!check_base_service_activated (context, connection,
2495                                          message, &base_service))
2496         goto out;
2497 
2498       base_service_message = message;
2499       message = NULL;
2500 
2501       /* We may need to block here for the test service to exit or finish up */
2502       block_connection_until_message_from_bus (context, connection, "test service to exit or finish up");
2503 
2504       message = dbus_connection_borrow_message (connection);
2505       if (message == NULL)
2506         {
2507           _dbus_warn ("Did not receive any messages after base service creation notification\n");
2508           goto out;
2509         }
2510 
2511       message_kind = check_got_service_info (message);
2512 
2513       dbus_connection_return_message (connection, message);
2514       message = NULL;
2515 
2516       switch (message_kind)
2517         {
2518         case GOT_SOMETHING_ELSE:
2519           _dbus_warn ("Unexpected message after ActivateService "
2520                       "(should be an error or a service announcement");
2521           goto out;
2522 
2523         case GOT_ERROR:
2524           if (!check_got_error (context, connection,
2525                                 DBUS_ERROR_SPAWN_CHILD_EXITED,
2526                                 DBUS_ERROR_NO_MEMORY,
2527                                 NULL))
2528             goto out;
2529           /* A service deleted should be coming along now after this error.
2530            * We can also get the error *after* the service deleted.
2531            */
2532 
2533           /* fall through */
2534 
2535         case GOT_SERVICE_DELETED:
2536           {
2537             /* The service started up and got a base address, but then
2538              * failed to register under EXISTENT_SERVICE_NAME
2539              */
2540             CheckServiceOwnerChangedData socd;
2541 
2542             socd.expected_kind = SERVICE_DELETED;
2543             socd.expected_service_name = base_service;
2544             socd.failed = FALSE;
2545             socd.skip_connection = NULL;
2546 
2547             bus_test_clients_foreach (check_service_owner_changed_foreach,
2548                                       &socd);
2549 
2550             if (socd.failed)
2551               goto out;
2552 
2553             /* Now we should get an error about the service exiting
2554              * if we didn't get it before.
2555              */
2556             if (message_kind != GOT_ERROR)
2557               {
2558                 block_connection_until_message_from_bus (context, connection, "error about service exiting");
2559 
2560                 /* and process everything again */
2561                 bus_test_run_everything (context);
2562 
2563                 if (!check_got_error (context, connection,
2564                                       DBUS_ERROR_SPAWN_CHILD_EXITED,
2565 				      DBUS_ERROR_NO_MEMORY,
2566                                       NULL))
2567                   goto out;
2568               }
2569             break;
2570           }
2571 
2572         case GOT_SERVICE_CREATED:
2573           message = pop_message_waiting_for_memory (connection);
2574           if (message == NULL)
2575             {
2576               _dbus_warn ("Failed to pop message we just put back! "
2577                           "should have been a NameOwnerChanged (creation)\n");
2578               goto out;
2579             }
2580 
2581           if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
2582                                         base_service, message))
2583             goto out;
2584 
2585           dbus_message_unref (message);
2586           message = NULL;
2587 
2588           if (!check_no_leftovers (context))
2589             {
2590               _dbus_warn ("Messages were left over after successful activation\n");
2591               goto out;
2592             }
2593 
2594 	  if (!check_send_exit_to_service (context, connection,
2595                                            EXISTENT_SERVICE_NAME, base_service))
2596 	    goto out;
2597 
2598           break;
2599         }
2600     }
2601 
2602   retval = TRUE;
2603 
2604  out:
2605   if (message)
2606     dbus_message_unref (message);
2607 
2608   if (base_service_message)
2609     dbus_message_unref (base_service_message);
2610 
2611   return retval;
2612 }
2613 
2614 /* returns TRUE if the correct thing happens,
2615  * but the correct thing may include OOM errors.
2616  */
2617 static dbus_bool_t
check_segfault_service_no_auto_start(BusContext * context,DBusConnection * connection)2618 check_segfault_service_no_auto_start (BusContext     *context,
2619                                       DBusConnection *connection)
2620 {
2621   DBusMessage *message;
2622   dbus_uint32_t serial;
2623   dbus_bool_t retval;
2624   const char *segv_service;
2625   dbus_uint32_t flags;
2626 
2627   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
2628                                           DBUS_PATH_DBUS,
2629                                           DBUS_INTERFACE_DBUS,
2630                                           "StartServiceByName");
2631 
2632   if (message == NULL)
2633     return TRUE;
2634 
2635   dbus_message_set_auto_start (message, FALSE);
2636 
2637   segv_service = "org.freedesktop.DBus.TestSuiteSegfaultService";
2638   flags = 0;
2639   if (!dbus_message_append_args (message,
2640                                  DBUS_TYPE_STRING, &segv_service,
2641                                  DBUS_TYPE_UINT32, &flags,
2642                                  DBUS_TYPE_INVALID))
2643     {
2644       dbus_message_unref (message);
2645       return TRUE;
2646     }
2647 
2648   if (!dbus_connection_send (connection, message, &serial))
2649     {
2650       dbus_message_unref (message);
2651       return TRUE;
2652     }
2653 
2654   dbus_message_unref (message);
2655   message = NULL;
2656 
2657   bus_test_run_everything (context);
2658   block_connection_until_message_from_bus (context, connection, "reply to activating segfault service");
2659   bus_test_run_everything (context);
2660 
2661   if (!dbus_connection_get_is_connected (connection))
2662     {
2663       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
2664       return TRUE;
2665     }
2666 
2667   retval = FALSE;
2668 
2669   message = pop_message_waiting_for_memory (connection);
2670   if (message == NULL)
2671     {
2672       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
2673                   "StartServiceByName", serial, connection);
2674       goto out;
2675     }
2676 
2677   verbose_message_received (connection, message);
2678 
2679   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2680     {
2681       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
2682         {
2683           _dbus_warn ("Message has wrong sender %s\n",
2684                       dbus_message_get_sender (message) ?
2685                       dbus_message_get_sender (message) : "(none)");
2686           goto out;
2687         }
2688 
2689       if (dbus_message_is_error (message,
2690                                  DBUS_ERROR_NO_MEMORY))
2691         {
2692           ; /* good, this is a valid response */
2693         }
2694       else if (dbus_message_is_error (message,
2695                                       DBUS_ERROR_SPAWN_CHILD_SIGNALED))
2696         {
2697           ; /* good, this is expected also */
2698         }
2699       else
2700         {
2701           warn_unexpected (connection, message, "not this error");
2702 
2703           goto out;
2704         }
2705     }
2706   else
2707     {
2708       _dbus_warn ("Did not expect to successfully activate segfault service\n");
2709       goto out;
2710     }
2711 
2712   retval = TRUE;
2713 
2714  out:
2715   if (message)
2716     dbus_message_unref (message);
2717 
2718   return retval;
2719 }
2720 
2721 
2722 /* returns TRUE if the correct thing happens,
2723  * but the correct thing may include OOM errors.
2724  */
2725 static dbus_bool_t
check_segfault_service_auto_start(BusContext * context,DBusConnection * connection)2726 check_segfault_service_auto_start (BusContext     *context,
2727                                    DBusConnection *connection)
2728 {
2729   DBusMessage *message;
2730   dbus_uint32_t serial;
2731   dbus_bool_t retval;
2732 
2733   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteSegfaultService",
2734                                           "/org/freedesktop/TestSuite",
2735                                           "org.freedesktop.TestSuite",
2736                                           "Echo");
2737 
2738   if (message == NULL)
2739     return TRUE;
2740 
2741   if (!dbus_connection_send (connection, message, &serial))
2742     {
2743       dbus_message_unref (message);
2744       return TRUE;
2745     }
2746 
2747   dbus_message_unref (message);
2748   message = NULL;
2749 
2750   bus_test_run_everything (context);
2751   block_connection_until_message_from_bus (context, connection, "reply to Echo on segfault service");
2752   bus_test_run_everything (context);
2753 
2754   if (!dbus_connection_get_is_connected (connection))
2755     {
2756       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
2757       return TRUE;
2758     }
2759 
2760   retval = FALSE;
2761 
2762   message = pop_message_waiting_for_memory (connection);
2763   if (message == NULL)
2764     {
2765       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
2766                   "Echo message (auto activation)", serial, connection);
2767       goto out;
2768     }
2769 
2770   verbose_message_received (connection, message);
2771 
2772   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2773     {
2774       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
2775         {
2776           _dbus_warn ("Message has wrong sender %s\n",
2777                       dbus_message_get_sender (message) ?
2778                       dbus_message_get_sender (message) : "(none)");
2779           goto out;
2780         }
2781 
2782       if (dbus_message_is_error (message,
2783                                  DBUS_ERROR_NO_MEMORY))
2784         {
2785           ; /* good, this is a valid response */
2786         }
2787       else if (dbus_message_is_error (message,
2788                                       DBUS_ERROR_SPAWN_CHILD_SIGNALED))
2789         {
2790           ; /* good, this is expected also */
2791         }
2792       else
2793         {
2794           warn_unexpected (connection, message, "not this error");
2795 
2796           goto out;
2797         }
2798     }
2799   else
2800     {
2801       _dbus_warn ("Did not expect to successfully activate segfault service\n");
2802       goto out;
2803     }
2804 
2805   retval = TRUE;
2806 
2807  out:
2808   if (message)
2809     dbus_message_unref (message);
2810 
2811   return retval;
2812 }
2813 
2814 #define TEST_ECHO_MESSAGE "Test echo message"
2815 #define TEST_RUN_HELLO_FROM_SELF_MESSAGE "Test sending message to self"
2816 
2817 /* returns TRUE if the correct thing happens,
2818  * but the correct thing may include OOM errors.
2819  */
2820 static dbus_bool_t
check_existent_hello_from_self(BusContext * context,DBusConnection * connection)2821 check_existent_hello_from_self (BusContext     *context,
2822                                 DBusConnection *connection)
2823 {
2824   DBusMessage *message;
2825   dbus_uint32_t serial;
2826   const char *text;
2827 
2828   message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
2829                                           "/org/freedesktop/TestSuite",
2830                                           "org.freedesktop.TestSuite",
2831                                           "RunHelloFromSelf");
2832 
2833   if (message == NULL)
2834     return TRUE;
2835 
2836   text = TEST_RUN_HELLO_FROM_SELF_MESSAGE;
2837   if (!dbus_message_append_args (message,
2838                                  DBUS_TYPE_STRING, &text,
2839                                  DBUS_TYPE_INVALID))
2840     {
2841       dbus_message_unref (message);
2842       return TRUE;
2843     }
2844 
2845   if (!dbus_connection_send (connection, message, &serial))
2846     {
2847       dbus_message_unref (message);
2848       return TRUE;
2849     }
2850 
2851   dbus_message_unref (message);
2852   message = NULL;
2853 
2854   bus_test_run_everything (context);
2855 
2856   /* Note: if this test is run in OOM mode, it will block when the bus
2857    * doesn't send a reply due to OOM.
2858    */
2859   block_connection_until_message_from_bus (context, connection, "reply from running hello from self");
2860 
2861   message = pop_message_waiting_for_memory (connection);
2862   if (message == NULL)
2863     {
2864       _dbus_warn ("Failed to pop message! Should have been reply from RunHelloFromSelf message\n");
2865       return FALSE;
2866     }
2867 
2868   if (dbus_message_get_reply_serial (message) != serial)
2869     {
2870       _dbus_warn ("Wrong reply serial\n");
2871       dbus_message_unref (message);
2872       return FALSE;
2873     }
2874 
2875   dbus_message_unref (message);
2876   message = NULL;
2877 
2878   return TRUE;
2879 }
2880 
2881 /* returns TRUE if the correct thing happens,
2882  * but the correct thing may include OOM errors.
2883  */
2884 static dbus_bool_t
check_existent_ping(BusContext * context,DBusConnection * connection)2885 check_existent_ping (BusContext     *context,
2886                      DBusConnection *connection)
2887 {
2888   DBusMessage *message;
2889   dbus_uint32_t serial;
2890   message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
2891                                           "/org/freedesktop/TestSuite",
2892                                           "org.freedesktop.DBus.Peer",
2893                                           "Ping");
2894 
2895   if (message == NULL)
2896     return TRUE;
2897 
2898   if (!dbus_connection_send (connection, message, &serial))
2899     {
2900       dbus_message_unref (message);
2901       return TRUE;
2902     }
2903 
2904   dbus_message_unref (message);
2905   message = NULL;
2906 
2907   bus_test_run_everything (context);
2908 
2909   /* Note: if this test is run in OOM mode, it will block when the bus
2910    * doesn't send a reply due to OOM.
2911    */
2912   block_connection_until_message_from_bus (context, connection, "reply from running Ping");
2913 
2914   message = pop_message_waiting_for_memory (connection);
2915   if (message == NULL)
2916     {
2917       _dbus_warn ("Failed to pop message! Should have been reply from Ping message\n");
2918       return FALSE;
2919     }
2920 
2921   if (dbus_message_get_reply_serial (message) != serial)
2922     {
2923       _dbus_warn ("Wrong reply serial\n");
2924       dbus_message_unref (message);
2925       return FALSE;
2926     }
2927 
2928   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
2929     {
2930       _dbus_warn ("Unexpected message return during Ping\n");
2931       dbus_message_unref (message);
2932       return FALSE;
2933     }
2934 
2935   dbus_message_unref (message);
2936   message = NULL;
2937 
2938   return TRUE;
2939 }
2940 
2941 /* returns TRUE if the correct thing happens,
2942  * but the correct thing may include OOM errors.
2943  */
2944 static dbus_bool_t
check_existent_get_machine_id(BusContext * context,DBusConnection * connection)2945 check_existent_get_machine_id (BusContext     *context,
2946                                DBusConnection *connection)
2947 {
2948   DBusMessage *message;
2949   dbus_uint32_t serial;
2950   const char *machine_id;
2951 
2952   message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
2953                                           "/org/freedesktop/TestSuite",
2954                                           "org.freedesktop.DBus.Peer",
2955                                           "GetMachineId");
2956 
2957   if (message == NULL)
2958     return TRUE;
2959 
2960   if (!dbus_connection_send (connection, message, &serial))
2961     {
2962       dbus_message_unref (message);
2963       return TRUE;
2964     }
2965 
2966   dbus_message_unref (message);
2967   message = NULL;
2968 
2969   bus_test_run_everything (context);
2970 
2971   /* Note: if this test is run in OOM mode, it will block when the bus
2972    * doesn't send a reply due to OOM.
2973    */
2974   block_connection_until_message_from_bus (context, connection, "reply from running GetMachineId");
2975 
2976   message = pop_message_waiting_for_memory (connection);
2977   if (message == NULL)
2978     {
2979       _dbus_warn ("Failed to pop message! Should have been reply from GetMachineId message\n");
2980       return FALSE;
2981     }
2982 
2983   if (dbus_message_get_reply_serial (message) != serial)
2984     {
2985       _dbus_warn ("Wrong reply serial\n");
2986       dbus_message_unref (message);
2987       return FALSE;
2988     }
2989 
2990   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
2991     {
2992       _dbus_warn ("Unexpected message return during GetMachineId\n");
2993       dbus_message_unref (message);
2994       return FALSE;
2995     }
2996 
2997   machine_id = NULL;
2998   if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &machine_id, DBUS_TYPE_INVALID))
2999     {
3000       _dbus_warn ("Did not get a machine ID in reply to GetMachineId\n");
3001       dbus_message_unref (message);
3002       return FALSE;
3003     }
3004 
3005   if (machine_id == NULL || strlen (machine_id) != 32)
3006     {
3007       _dbus_warn ("Machine id looks bogus: '%s'\n", machine_id ? machine_id : "null");
3008       dbus_message_unref (message);
3009       return FALSE;
3010     }
3011 
3012   /* We can't check that the machine id is correct because during make check it is
3013    * just made up for each process separately
3014    */
3015 
3016   dbus_message_unref (message);
3017   message = NULL;
3018 
3019   return TRUE;
3020 }
3021 
3022 /* returns TRUE if the correct thing happens,
3023  * but the correct thing may include OOM errors.
3024  */
3025 static dbus_bool_t
check_existent_service_auto_start(BusContext * context,DBusConnection * connection)3026 check_existent_service_auto_start (BusContext     *context,
3027                                    DBusConnection *connection)
3028 {
3029   DBusMessage *message;
3030   DBusMessage *base_service_message;
3031   dbus_uint32_t serial;
3032   dbus_bool_t retval;
3033   const char *base_service;
3034   const char *text;
3035 
3036   base_service_message = NULL;
3037 
3038   message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
3039                                           "/org/freedesktop/TestSuite",
3040                                           "org.freedesktop.TestSuite",
3041                                           "Echo");
3042 
3043   if (message == NULL)
3044     return TRUE;
3045 
3046   text = TEST_ECHO_MESSAGE;
3047   if (!dbus_message_append_args (message,
3048                                  DBUS_TYPE_STRING, &text,
3049                                  DBUS_TYPE_INVALID))
3050     {
3051       dbus_message_unref (message);
3052       return TRUE;
3053     }
3054 
3055   if (!dbus_connection_send (connection, message, &serial))
3056     {
3057       dbus_message_unref (message);
3058       return TRUE;
3059     }
3060 
3061   dbus_message_unref (message);
3062   message = NULL;
3063 
3064   bus_test_run_everything (context);
3065 
3066   /* now wait for the message bus to hear back from the activated
3067    * service.
3068    */
3069   block_connection_until_message_from_bus (context, connection, "reply to Echo on existent service");
3070   bus_test_run_everything (context);
3071 
3072   if (!dbus_connection_get_is_connected (connection))
3073     {
3074       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
3075       return TRUE;
3076     }
3077 
3078   retval = FALSE;
3079 
3080   message = pop_message_waiting_for_memory (connection);
3081   if (message == NULL)
3082     {
3083       _dbus_warn ("Did not receive any messages after auto start %d on %p\n",
3084                   serial, connection);
3085       goto out;
3086     }
3087 
3088   verbose_message_received (connection, message);
3089   _dbus_verbose ("  (after sending %s)\n", "auto start");
3090 
3091   /* we should get zero or two ServiceOwnerChanged signals */
3092   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL)
3093     {
3094       GotServiceInfo message_kind;
3095 
3096       if (!check_base_service_activated (context, connection,
3097                                          message, &base_service))
3098         goto out;
3099 
3100       base_service_message = message;
3101       message = NULL;
3102 
3103       /* We may need to block here for the test service to exit or finish up */
3104       block_connection_until_message_from_bus (context, connection, "service to exit");
3105 
3106       /* Should get a service creation notification for the activated
3107        * service name, or a service deletion on the base service name
3108        */
3109       message = dbus_connection_borrow_message (connection);
3110       if (message == NULL)
3111         {
3112           _dbus_warn ("No message after auto activation "
3113                       "(should be a service announcement)\n");
3114           dbus_connection_return_message (connection, message);
3115           message = NULL;
3116           goto out;
3117         }
3118 
3119       message_kind = check_got_service_info (message);
3120 
3121       dbus_connection_return_message (connection, message);
3122       message = NULL;
3123 
3124       switch (message_kind)
3125         {
3126         case GOT_SERVICE_CREATED:
3127           message = pop_message_waiting_for_memory (connection);
3128           if (message == NULL)
3129             {
3130               _dbus_warn ("Failed to pop message we just put back! "
3131                           "should have been a NameOwnerChanged (creation)\n");
3132               goto out;
3133             }
3134 
3135           /* Check that ServiceOwnerChanged (creation) was correctly received */
3136           if (!check_service_auto_activated (context, connection, EXISTENT_SERVICE_NAME,
3137                                              base_service, message))
3138             goto out;
3139 
3140           dbus_message_unref (message);
3141           message = NULL;
3142 
3143           break;
3144 
3145         case GOT_SERVICE_DELETED:
3146           {
3147             /* The service started up and got a base address, but then
3148              * failed to register under EXISTENT_SERVICE_NAME
3149              */
3150             CheckServiceOwnerChangedData socd;
3151 
3152             socd.expected_kind = SERVICE_DELETED;
3153             socd.expected_service_name = base_service;
3154             socd.failed = FALSE;
3155             socd.skip_connection = NULL;
3156             bus_test_clients_foreach (check_service_owner_changed_foreach,
3157                                       &socd);
3158 
3159             if (socd.failed)
3160               goto out;
3161 
3162             break;
3163           }
3164 
3165         case GOT_ERROR:
3166         case GOT_SOMETHING_ELSE:
3167           _dbus_warn ("Unexpected message after auto activation\n");
3168           goto out;
3169         }
3170     }
3171 
3172   /* OK, now we've dealt with ServiceOwnerChanged signals, now should
3173    * come the method reply (or error) from the initial method call
3174    */
3175 
3176   /* Note: if this test is run in OOM mode, it will block when the bus
3177    * doesn't send a reply due to OOM.
3178    */
3179   block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation");
3180 
3181   message = pop_message_waiting_for_memory (connection);
3182   if (message == NULL)
3183     {
3184       _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
3185       goto out;
3186     }
3187 
3188   if (dbus_message_get_reply_serial (message) != serial)
3189     {
3190       _dbus_warn ("Wrong reply serial\n");
3191       goto out;
3192     }
3193 
3194   dbus_message_unref (message);
3195   message = NULL;
3196 
3197   if (!check_existent_ping (context, connection))
3198     goto out;
3199 
3200   if (!check_existent_get_machine_id (context, connection))
3201     goto out;
3202 
3203   if (!check_existent_hello_from_self (context, connection))
3204     goto out;
3205 
3206   if (!check_send_exit_to_service (context, connection,
3207                                    EXISTENT_SERVICE_NAME,
3208                                    base_service))
3209     goto out;
3210 
3211   retval = TRUE;
3212 
3213  out:
3214   if (message)
3215     dbus_message_unref (message);
3216 
3217   if (base_service_message)
3218     dbus_message_unref (base_service_message);
3219 
3220   return retval;
3221 }
3222 
3223 #define SHELL_FAIL_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceFail"
3224 
3225 /* returns TRUE if the correct thing happens,
3226  * but the correct thing may include OOM errors.
3227  */
3228 static dbus_bool_t
check_shell_fail_service_auto_start(BusContext * context,DBusConnection * connection)3229 check_shell_fail_service_auto_start (BusContext     *context,
3230                                      DBusConnection *connection)
3231 {
3232   DBusMessage *message;
3233   dbus_uint32_t serial;
3234   dbus_bool_t retval;
3235 
3236   message = dbus_message_new_method_call (SHELL_FAIL_SERVICE_NAME,
3237                                           "/org/freedesktop/TestSuite",
3238                                           "org.freedesktop.TestSuite",
3239                                           "Echo");
3240 
3241   if (message == NULL)
3242     return TRUE;
3243 
3244   if (!dbus_connection_send (connection, message, &serial))
3245     {
3246       dbus_message_unref (message);
3247       return TRUE;
3248     }
3249 
3250   dbus_message_unref (message);
3251   message = NULL;
3252 
3253   bus_test_run_everything (context);
3254   block_connection_until_message_from_bus (context, connection, "reply to shell Echo on service which should fail to auto-start");
3255   bus_test_run_everything (context);
3256 
3257   if (!dbus_connection_get_is_connected (connection))
3258     {
3259       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
3260       return TRUE;
3261     }
3262 
3263   retval = FALSE;
3264 
3265   message = pop_message_waiting_for_memory (connection);
3266   if (message == NULL)
3267     {
3268       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
3269                   "Echo message (auto activation)", serial, connection);
3270       goto out;
3271     }
3272 
3273   verbose_message_received (connection, message);
3274 
3275   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3276     {
3277       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3278         {
3279           _dbus_warn ("Message has wrong sender %s\n",
3280                       dbus_message_get_sender (message) ?
3281                       dbus_message_get_sender (message) : "(none)");
3282           goto out;
3283         }
3284 
3285       if (dbus_message_is_error (message,
3286                                  DBUS_ERROR_NO_MEMORY))
3287         {
3288           ; /* good, this is a valid response */
3289         }
3290       else if (dbus_message_is_error (message,
3291                                       DBUS_ERROR_INVALID_ARGS))
3292         {
3293           _dbus_verbose("got invalid args\n");
3294           ; /* good, this is expected also */
3295         }
3296       else
3297         {
3298           warn_unexpected (connection, message, "not this error");
3299 
3300           goto out;
3301         }
3302     }
3303   else
3304     {
3305       _dbus_warn ("Did not expect to successfully auto-start shell fail service\n");
3306       goto out;
3307     }
3308 
3309   retval = TRUE;
3310 
3311  out:
3312   if (message)
3313     dbus_message_unref (message);
3314 
3315   return retval;
3316 }
3317 
3318 #define SHELL_SUCCESS_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess"
3319 
3320 /* returns TRUE if the correct thing happens,
3321  * but the correct thing may include OOM errors.
3322  */
3323 static dbus_bool_t
check_shell_service_success_auto_start(BusContext * context,DBusConnection * connection)3324 check_shell_service_success_auto_start (BusContext     *context,
3325                                         DBusConnection *connection)
3326 {
3327   DBusMessage *message;
3328   DBusMessage *base_service_message;
3329   dbus_uint32_t serial;
3330   dbus_bool_t retval;
3331   const char *base_service;
3332   const char *argv[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
3333 
3334   base_service_message = NULL;
3335 
3336   message = dbus_message_new_method_call (SHELL_SUCCESS_SERVICE_NAME,
3337                                           "/org/freedesktop/TestSuite",
3338                                           "org.freedesktop.TestSuite",
3339                                           "Echo");
3340 
3341   if (message == NULL)
3342     return TRUE;
3343 
3344   if (!dbus_connection_send (connection, message, &serial))
3345     {
3346       dbus_message_unref (message);
3347       return TRUE;
3348     }
3349 
3350   dbus_message_unref (message);
3351   message = NULL;
3352 
3353   bus_test_run_everything (context);
3354 
3355   /* now wait for the message bus to hear back from the activated
3356    * service.
3357    */
3358   block_connection_until_message_from_bus (context, connection, "reply to Echo on shell success service");
3359   bus_test_run_everything (context);
3360 
3361   if (!dbus_connection_get_is_connected (connection))
3362     {
3363       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
3364       return TRUE;
3365     }
3366 
3367   retval = FALSE;
3368 
3369   message = pop_message_waiting_for_memory (connection);
3370   if (message == NULL)
3371     {
3372       _dbus_warn ("Did not receive any messages after auto start %d on %p\n",
3373                   serial, connection);
3374       goto out;
3375     }
3376 
3377   verbose_message_received (connection, message);
3378   _dbus_verbose ("  (after sending %s)\n", "auto start");
3379 
3380   /* we should get zero or two ServiceOwnerChanged signals */
3381   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL)
3382     {
3383       GotServiceInfo message_kind;
3384 
3385       if (!check_base_service_activated (context, connection,
3386                                          message, &base_service))
3387         goto out;
3388 
3389       base_service_message = message;
3390       message = NULL;
3391 
3392       /* We may need to block here for the test service to exit or finish up */
3393       block_connection_until_message_from_bus (context, connection, "service to exit");
3394 
3395       /* Should get a service creation notification for the activated
3396        * service name, or a service deletion on the base service name
3397        */
3398       message = dbus_connection_borrow_message (connection);
3399       if (message == NULL)
3400         {
3401           _dbus_warn ("No message after auto activation "
3402                       "(should be a service announcement)\n");
3403           dbus_connection_return_message (connection, message);
3404           message = NULL;
3405           goto out;
3406         }
3407 
3408       message_kind = check_got_service_info (message);
3409 
3410       dbus_connection_return_message (connection, message);
3411       message = NULL;
3412 
3413       switch (message_kind)
3414         {
3415         case GOT_SERVICE_CREATED:
3416           message = pop_message_waiting_for_memory (connection);
3417           if (message == NULL)
3418             {
3419               _dbus_warn ("Failed to pop message we just put back! "
3420                           "should have been a NameOwnerChanged (creation)\n");
3421               goto out;
3422             }
3423 
3424           /* Check that ServiceOwnerChanged (creation) was correctly received */
3425           if (!check_service_auto_activated (context, connection, SHELL_SUCCESS_SERVICE_NAME,
3426                                              base_service, message))
3427             goto out;
3428 
3429           dbus_message_unref (message);
3430           message = NULL;
3431 
3432           break;
3433 
3434         case GOT_SERVICE_DELETED:
3435           {
3436             /* The service started up and got a base address, but then
3437              * failed to register under SHELL_SUCCESS_SERVICE_NAME
3438              */
3439             CheckServiceOwnerChangedData socd;
3440 
3441             socd.expected_kind = SERVICE_DELETED;
3442             socd.expected_service_name = base_service;
3443             socd.failed = FALSE;
3444             socd.skip_connection = NULL;
3445             bus_test_clients_foreach (check_service_owner_changed_foreach,
3446                                       &socd);
3447 
3448             if (socd.failed)
3449               goto out;
3450 
3451             break;
3452           }
3453 
3454         case GOT_ERROR:
3455         case GOT_SOMETHING_ELSE:
3456           _dbus_warn ("Unexpected message after auto activation\n");
3457           goto out;
3458         }
3459     }
3460 
3461   /* OK, now we've dealt with ServiceOwnerChanged signals, now should
3462    * come the method reply (or error) from the initial method call
3463    */
3464 
3465   /* Note: if this test is run in OOM mode, it will block when the bus
3466    * doesn't send a reply due to OOM.
3467    */
3468   block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation");
3469 
3470   message = pop_message_waiting_for_memory (connection);
3471   if (message == NULL)
3472     {
3473       _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
3474       goto out;
3475     }
3476 
3477   if (dbus_message_get_reply_serial (message) != serial)
3478     {
3479       _dbus_warn ("Wrong reply serial\n");
3480       goto out;
3481     }
3482 
3483   if (!dbus_message_get_args (message, NULL,
3484                                        DBUS_TYPE_STRING, &argv[0],
3485                                        DBUS_TYPE_STRING, &argv[1],
3486                                        DBUS_TYPE_STRING, &argv[2],
3487                                        DBUS_TYPE_STRING, &argv[3],
3488                                        DBUS_TYPE_STRING, &argv[4],
3489                                        DBUS_TYPE_STRING, &argv[5],
3490                                        DBUS_TYPE_STRING, &argv[6],
3491                                        DBUS_TYPE_INVALID))
3492     {
3493       _dbus_warn ("Error getting arguments from return\n");
3494       goto out;
3495     }
3496 
3497    /* don't worry about arg[0] as it may be different
3498       depending on the path to the tests
3499    */
3500   if (strcmp("-test", argv[1]) != 0)
3501     {
3502       _dbus_warn ("Unexpected argv[1] in shell success service test (expected: %s, got: %s)\n",
3503                   "-test", argv[1]);
3504       goto out;
3505     }
3506 
3507   if (strcmp("that", argv[2]) != 0)
3508     {
3509       _dbus_warn ("Unexpected argv[2] in shell success service test (expected: %s, got: %s)\n",
3510                    "that", argv[2]);
3511       goto out;
3512     }
3513 
3514   if (strcmp("we get", argv[3]) != 0)
3515     {
3516       _dbus_warn ("Unexpected argv[3] in shell success service test (expected: %s, got: %s)\n",
3517                    "we get", argv[3]);
3518       goto out;
3519     }
3520 
3521   if (strcmp("back", argv[4]) != 0)
3522     {
3523       _dbus_warn ("Unexpected argv[4] in shell success service test (expected: %s, got: %s)\n",
3524                    "back", argv[4]);
3525       goto out;
3526     }
3527 
3528   if (strcmp("--what", argv[5]) != 0)
3529     {
3530       _dbus_warn ("Unexpected argv[5] in shell success service test (expected: %s, got: %s)\n",
3531                    "--what", argv[5]);
3532       goto out;
3533     }
3534 
3535   if (strcmp("we put in", argv[6]) != 0)
3536     {
3537       _dbus_warn ("Unexpected argv[6] in shell success service test (expected: %s, got: %s)\n",
3538                    "we put in", argv[6]);
3539       goto out;
3540     }
3541 
3542   dbus_message_unref (message);
3543   message = NULL;
3544 
3545   if (!check_send_exit_to_service (context, connection,
3546                                    SHELL_SUCCESS_SERVICE_NAME,
3547                                    base_service))
3548     goto out;
3549 
3550   retval = TRUE;
3551 
3552  out:
3553   if (message)
3554     dbus_message_unref (message);
3555 
3556   if (base_service_message)
3557     dbus_message_unref (base_service_message);
3558 
3559   return retval;
3560 }
3561 
3562 typedef struct
3563 {
3564   Check1Func func;
3565   BusContext *context;
3566 } Check1Data;
3567 
3568 static dbus_bool_t
check_oom_check1_func(void * data)3569 check_oom_check1_func (void *data)
3570 {
3571   Check1Data *d = data;
3572 
3573   if (! (* d->func) (d->context))
3574     return FALSE;
3575 
3576   if (!check_no_leftovers (d->context))
3577     {
3578       _dbus_warn ("Messages were left over, should be covered by test suite\n");
3579       return FALSE;
3580     }
3581 
3582   return TRUE;
3583 }
3584 
3585 static void
check1_try_iterations(BusContext * context,const char * description,Check1Func func)3586 check1_try_iterations (BusContext *context,
3587                        const char *description,
3588                        Check1Func  func)
3589 {
3590   Check1Data d;
3591 
3592   d.func = func;
3593   d.context = context;
3594 
3595   if (!_dbus_test_oom_handling (description, check_oom_check1_func,
3596                                 &d))
3597     _dbus_assert_not_reached ("test failed");
3598 }
3599 
3600 static dbus_bool_t
check_get_services(BusContext * context,DBusConnection * connection,const char * method,char *** services,int * len)3601 check_get_services (BusContext     *context,
3602 		    DBusConnection *connection,
3603 		    const char     *method,
3604 		    char         ***services,
3605 		    int            *len)
3606 {
3607   DBusMessage *message;
3608   dbus_uint32_t serial;
3609   dbus_bool_t retval;
3610   DBusError error;
3611   char **srvs;
3612   int l;
3613 
3614   retval = FALSE;
3615   dbus_error_init (&error);
3616   message = NULL;
3617 
3618   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
3619 					  DBUS_PATH_DBUS,
3620 					  DBUS_INTERFACE_DBUS,
3621 					  method);
3622 
3623   if (message == NULL)
3624     return TRUE;
3625 
3626   if (!dbus_connection_send (connection, message, &serial))
3627     {
3628       dbus_message_unref (message);
3629       return TRUE;
3630     }
3631 
3632   /* send our message */
3633   bus_test_run_clients_loop (SEND_PENDING (connection));
3634 
3635   dbus_message_unref (message);
3636   message = NULL;
3637 
3638   dbus_connection_ref (connection); /* because we may get disconnected */
3639   block_connection_until_message_from_bus (context, connection, "reply to ListActivatableNames/ListNames");
3640 
3641   if (!dbus_connection_get_is_connected (connection))
3642     {
3643       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
3644 
3645       dbus_connection_unref (connection);
3646 
3647       return TRUE;
3648     }
3649 
3650   dbus_connection_unref (connection);
3651 
3652   message = pop_message_waiting_for_memory (connection);
3653   if (message == NULL)
3654     {
3655       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
3656 		  method, serial, connection);
3657       goto out;
3658     }
3659 
3660   verbose_message_received (connection, message);
3661 
3662   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3663     {
3664       if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
3665 	{
3666 	  ; /* good, this is a valid response */
3667 	}
3668       else
3669 	{
3670 	  warn_unexpected (connection, message, "not this error");
3671 
3672 	  goto out;
3673 	}
3674     }
3675   else
3676     {
3677       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
3678 	{
3679 	  ; /* good, expected */
3680 	}
3681       else
3682 	{
3683 	  warn_unexpected (connection, message,
3684 			   "method_return for ListActivatableNames/ListNames");
3685 
3686 	  goto out;
3687 	}
3688 
3689     retry_get_property:
3690 
3691       if (!dbus_message_get_args (message, &error,
3692 				  DBUS_TYPE_ARRAY,
3693 				  DBUS_TYPE_STRING,
3694 				  &srvs, &l,
3695 				  DBUS_TYPE_INVALID))
3696 	{
3697 	  if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
3698 	    {
3699 	      _dbus_verbose ("no memory to list services by %s\n", method);
3700 	      dbus_error_free (&error);
3701 	      _dbus_wait_for_memory ();
3702 	      goto retry_get_property;
3703 	    }
3704 	  else
3705 	    {
3706 	      _dbus_assert (dbus_error_is_set (&error));
3707 	      _dbus_warn ("Did not get the expected DBUS_TYPE_ARRAY from %s\n", method);
3708 	      goto out;
3709 	    }
3710 	} else {
3711 	  *services = srvs;
3712 	  *len = l;
3713 	}
3714     }
3715 
3716   if (!check_no_leftovers (context))
3717     goto out;
3718 
3719   retval = TRUE;
3720 
3721  out:
3722   dbus_error_free (&error);
3723 
3724   if (message)
3725     dbus_message_unref (message);
3726 
3727   return retval;
3728 }
3729 
3730 /* returns TRUE if the correct thing happens,
3731  * but the correct thing may include OOM errors.
3732  */
3733 static dbus_bool_t
check_list_services(BusContext * context,DBusConnection * connection)3734 check_list_services (BusContext     *context,
3735 		     DBusConnection *connection)
3736 {
3737   DBusMessage  *message;
3738   DBusMessage  *base_service_message;
3739   const char   *base_service;
3740   dbus_uint32_t serial;
3741   dbus_bool_t   retval;
3742   const char   *existent = EXISTENT_SERVICE_NAME;
3743   dbus_uint32_t flags;
3744   char        **services;
3745   int           len;
3746 
3747   _dbus_verbose ("check_list_services for %p\n", connection);
3748 
3749   if (!check_get_services (context, connection, "ListActivatableNames", &services, &len))
3750     {
3751       return TRUE;
3752     }
3753 
3754   if (!_dbus_string_array_contains ((const char **)services, existent))
3755     {
3756       _dbus_warn ("Did not get the expected %s from ListActivatableNames\n", existent);
3757       return FALSE;
3758     }
3759 
3760   dbus_free_string_array (services);
3761 
3762   base_service_message = NULL;
3763 
3764   message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
3765 					  DBUS_PATH_DBUS,
3766 					  DBUS_INTERFACE_DBUS,
3767 					  "StartServiceByName");
3768 
3769   if (message == NULL)
3770     return TRUE;
3771 
3772   dbus_message_set_auto_start (message, FALSE);
3773 
3774   flags = 0;
3775   if (!dbus_message_append_args (message,
3776 				 DBUS_TYPE_STRING, &existent,
3777 				 DBUS_TYPE_UINT32, &flags,
3778 				 DBUS_TYPE_INVALID))
3779     {
3780       dbus_message_unref (message);
3781       return TRUE;
3782     }
3783 
3784   if (!dbus_connection_send (connection, message, &serial))
3785     {
3786       dbus_message_unref (message);
3787       return TRUE;
3788     }
3789 
3790   dbus_message_unref (message);
3791   message = NULL;
3792 
3793   bus_test_run_everything (context);
3794 
3795   /* now wait for the message bus to hear back from the activated
3796    * service.
3797    */
3798   block_connection_until_message_from_bus (context, connection, "activated service to connect");
3799 
3800   bus_test_run_everything (context);
3801 
3802   if (!dbus_connection_get_is_connected (connection))
3803     {
3804       _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
3805       return TRUE;
3806     }
3807 
3808   retval = FALSE;
3809 
3810   message = pop_message_waiting_for_memory (connection);
3811   if (message == NULL)
3812     {
3813       _dbus_warn ("Did not receive any messages after %s %d on %p\n",
3814 		  "StartServiceByName", serial, connection);
3815       goto out;
3816     }
3817 
3818   verbose_message_received (connection, message);
3819   _dbus_verbose ("  (after sending %s)\n", "StartServiceByName");
3820 
3821   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3822     {
3823       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3824 	{
3825 	  _dbus_warn ("Message has wrong sender %s\n",
3826 		      dbus_message_get_sender (message) ?
3827 		      dbus_message_get_sender (message) : "(none)");
3828 	  goto out;
3829 	}
3830 
3831       if (dbus_message_is_error (message,
3832 				 DBUS_ERROR_NO_MEMORY))
3833 	{
3834 	  ; /* good, this is a valid response */
3835 	}
3836       else if (dbus_message_is_error (message,
3837 				      DBUS_ERROR_SPAWN_CHILD_EXITED) ||
3838 	       dbus_message_is_error (message,
3839 				      DBUS_ERROR_SPAWN_CHILD_SIGNALED) ||
3840 	       dbus_message_is_error (message,
3841 				      DBUS_ERROR_SPAWN_EXEC_FAILED))
3842 	{
3843 	  ; /* good, this is expected also */
3844 	}
3845       else
3846 	{
3847 	  _dbus_warn ("Did not expect error %s\n",
3848 		      dbus_message_get_error_name (message));
3849 	  goto out;
3850 	}
3851     }
3852   else
3853     {
3854       GotServiceInfo message_kind;
3855 
3856       if (!check_base_service_activated (context, connection,
3857 					 message, &base_service))
3858 	goto out;
3859 
3860       base_service_message = message;
3861       message = NULL;
3862 
3863       /* We may need to block here for the test service to exit or finish up */
3864       block_connection_until_message_from_bus (context, connection, "test service to exit or finish up");
3865 
3866       message = dbus_connection_borrow_message (connection);
3867       if (message == NULL)
3868 	{
3869 	  _dbus_warn ("Did not receive any messages after base service creation notification\n");
3870 	  goto out;
3871 	}
3872 
3873       message_kind = check_got_service_info (message);
3874 
3875       dbus_connection_return_message (connection, message);
3876       message = NULL;
3877 
3878       switch (message_kind)
3879 	{
3880 	case GOT_SOMETHING_ELSE:
3881 	case GOT_ERROR:
3882 	case GOT_SERVICE_DELETED:
3883 	  _dbus_warn ("Unexpected message after ActivateService "
3884 		      "(should be an error or a service announcement)\n");
3885 	  goto out;
3886 
3887 	case GOT_SERVICE_CREATED:
3888 	  message = pop_message_waiting_for_memory (connection);
3889 	  if (message == NULL)
3890 	    {
3891 	      _dbus_warn ("Failed to pop message we just put back! "
3892 			  "should have been a NameOwnerChanged (creation)\n");
3893 	      goto out;
3894 	    }
3895 
3896 	  if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
3897 					base_service, message))
3898 	    goto out;
3899 
3900 	  dbus_message_unref (message);
3901 	  message = NULL;
3902 
3903 	  if (!check_no_leftovers (context))
3904 	    {
3905 	      _dbus_warn ("Messages were left over after successful activation\n");
3906 	      goto out;
3907 	    }
3908 
3909 	  break;
3910 	}
3911     }
3912 
3913   if (!check_get_services (context, connection, "ListNames", &services, &len))
3914     {
3915       return TRUE;
3916     }
3917 
3918   if (!_dbus_string_array_contains ((const char **)services, existent))
3919     {
3920       _dbus_warn ("Did not get the expected %s from ListNames\n", existent);
3921       goto out;
3922     }
3923 
3924   dbus_free_string_array (services);
3925 
3926   if (!check_send_exit_to_service (context, connection,
3927 				   EXISTENT_SERVICE_NAME, base_service))
3928     goto out;
3929 
3930   retval = TRUE;
3931 
3932  out:
3933   if (message)
3934     dbus_message_unref (message);
3935 
3936   if (base_service_message)
3937     dbus_message_unref (base_service_message);
3938 
3939   return retval;
3940 }
3941 
3942 typedef struct
3943 {
3944   Check2Func func;
3945   BusContext *context;
3946   DBusConnection *connection;
3947 } Check2Data;
3948 
3949 static dbus_bool_t
check_oom_check2_func(void * data)3950 check_oom_check2_func (void *data)
3951 {
3952   Check2Data *d = data;
3953 
3954   if (! (* d->func) (d->context, d->connection))
3955     return FALSE;
3956 
3957   if (!check_no_leftovers (d->context))
3958     {
3959       _dbus_warn ("Messages were left over, should be covered by test suite\n");
3960       return FALSE;
3961     }
3962 
3963   return TRUE;
3964 }
3965 
3966 static void
check2_try_iterations(BusContext * context,DBusConnection * connection,const char * description,Check2Func func)3967 check2_try_iterations (BusContext     *context,
3968                        DBusConnection *connection,
3969                        const char     *description,
3970                        Check2Func      func)
3971 {
3972   Check2Data d;
3973 
3974   d.func = func;
3975   d.context = context;
3976   d.connection = connection;
3977 
3978   if (!_dbus_test_oom_handling (description, check_oom_check2_func,
3979                                 &d))
3980     {
3981       _dbus_warn ("%s failed during oom\n", description);
3982       _dbus_assert_not_reached ("test failed");
3983     }
3984 }
3985 
3986 dbus_bool_t
bus_dispatch_test(const DBusString * test_data_dir)3987 bus_dispatch_test (const DBusString *test_data_dir)
3988 {
3989   BusContext *context;
3990   DBusConnection *foo;
3991   DBusConnection *bar;
3992   DBusConnection *baz;
3993   DBusError error;
3994 
3995   dbus_error_init (&error);
3996 
3997   context = bus_context_new_test (test_data_dir,
3998                                   "valid-config-files/debug-allow-all.conf");
3999   if (context == NULL)
4000     return FALSE;
4001 
4002   foo = dbus_connection_open_private ("debug-pipe:name=test-server", &error);
4003   if (foo == NULL)
4004     _dbus_assert_not_reached ("could not alloc connection");
4005 
4006   if (!bus_setup_debug_client (foo))
4007     _dbus_assert_not_reached ("could not set up connection");
4008 
4009   spin_connection_until_authenticated (context, foo);
4010 
4011   if (!check_hello_message (context, foo))
4012     _dbus_assert_not_reached ("hello message failed");
4013 
4014   if (!check_double_hello_message (context, foo))
4015     _dbus_assert_not_reached ("double hello message failed");
4016 
4017   if (!check_add_match_all (context, foo))
4018     _dbus_assert_not_reached ("AddMatch message failed");
4019 
4020   bar = dbus_connection_open_private ("debug-pipe:name=test-server", &error);
4021   if (bar == NULL)
4022     _dbus_assert_not_reached ("could not alloc connection");
4023 
4024   if (!bus_setup_debug_client (bar))
4025     _dbus_assert_not_reached ("could not set up connection");
4026 
4027   spin_connection_until_authenticated (context, bar);
4028 
4029   if (!check_hello_message (context, bar))
4030     _dbus_assert_not_reached ("hello message failed");
4031 
4032   if (!check_add_match_all (context, bar))
4033     _dbus_assert_not_reached ("AddMatch message failed");
4034 
4035   baz = dbus_connection_open_private ("debug-pipe:name=test-server", &error);
4036   if (baz == NULL)
4037     _dbus_assert_not_reached ("could not alloc connection");
4038 
4039   if (!bus_setup_debug_client (baz))
4040     _dbus_assert_not_reached ("could not set up connection");
4041 
4042   spin_connection_until_authenticated (context, baz);
4043 
4044   if (!check_hello_message (context, baz))
4045     _dbus_assert_not_reached ("hello message failed");
4046 
4047   if (!check_add_match_all (context, baz))
4048     _dbus_assert_not_reached ("AddMatch message failed");
4049 
4050   if (!check_get_connection_unix_user (context, baz))
4051     _dbus_assert_not_reached ("GetConnectionUnixUser message failed");
4052 
4053   if (!check_get_connection_unix_process_id (context, baz))
4054     _dbus_assert_not_reached ("GetConnectionUnixProcessID message failed");
4055 
4056   if (!check_list_services (context, baz))
4057     _dbus_assert_not_reached ("ListActivatableNames message failed");
4058 
4059   if (!check_no_leftovers (context))
4060     {
4061       _dbus_warn ("Messages were left over after setting up initial connections\n");
4062       _dbus_assert_not_reached ("initial connection setup failed");
4063     }
4064 
4065   check1_try_iterations (context, "create_and_hello",
4066                          check_hello_connection);
4067 
4068   check2_try_iterations (context, foo, "nonexistent_service_no_auto_start",
4069                          check_nonexistent_service_no_auto_start);
4070 
4071   check2_try_iterations (context, foo, "segfault_service_no_auto_start",
4072                          check_segfault_service_no_auto_start);
4073 
4074   check2_try_iterations (context, foo, "existent_service_no_auto_start",
4075                          check_existent_service_no_auto_start);
4076 
4077   check2_try_iterations (context, foo, "nonexistent_service_auto_start",
4078                          check_nonexistent_service_auto_start);
4079 
4080   check2_try_iterations (context, foo, "segfault_service_auto_start",
4081                          check_segfault_service_auto_start);
4082 
4083   check2_try_iterations (context, foo, "shell_fail_service_auto_start",
4084                          check_shell_fail_service_auto_start);
4085 
4086 #if 0
4087   /* Note: need to resolve some issues with the testing code in order to run
4088    * this in oom (handle that we sometimes don't get replies back from the bus
4089    * when oom happens, without blocking the test).
4090    */
4091   check2_try_iterations (context, foo, "existent_service_auto_auto_start",
4092                          check_existent_service_auto_start);
4093 #endif
4094 
4095   if (!check_existent_service_auto_start (context, foo))
4096     _dbus_assert_not_reached ("existent service auto start failed");
4097 
4098   if (!check_shell_service_success_auto_start (context, foo))
4099     _dbus_assert_not_reached ("shell success service auto start failed");
4100 
4101   _dbus_verbose ("Disconnecting foo, bar, and baz\n");
4102 
4103   kill_client_connection_unchecked (foo);
4104   kill_client_connection_unchecked (bar);
4105   kill_client_connection_unchecked (baz);
4106 
4107   bus_context_unref (context);
4108 
4109   return TRUE;
4110 }
4111 
4112 dbus_bool_t
bus_dispatch_sha1_test(const DBusString * test_data_dir)4113 bus_dispatch_sha1_test (const DBusString *test_data_dir)
4114 {
4115   BusContext *context;
4116   DBusConnection *foo;
4117   DBusError error;
4118 
4119   dbus_error_init (&error);
4120 
4121   /* Test SHA1 authentication */
4122   _dbus_verbose ("Testing SHA1 context\n");
4123 
4124   context = bus_context_new_test (test_data_dir,
4125                                   "valid-config-files/debug-allow-all-sha1.conf");
4126   if (context == NULL)
4127     return FALSE;
4128 
4129   foo = dbus_connection_open_private ("debug-pipe:name=test-server", &error);
4130   if (foo == NULL)
4131     _dbus_assert_not_reached ("could not alloc connection");
4132 
4133   if (!bus_setup_debug_client (foo))
4134     _dbus_assert_not_reached ("could not set up connection");
4135 
4136   spin_connection_until_authenticated (context, foo);
4137 
4138   if (!check_hello_message (context, foo))
4139     _dbus_assert_not_reached ("hello message failed");
4140 
4141   if (!check_add_match_all (context, foo))
4142     _dbus_assert_not_reached ("addmatch message failed");
4143 
4144   if (!check_no_leftovers (context))
4145     {
4146       _dbus_warn ("Messages were left over after setting up initial SHA-1 connection\n");
4147       _dbus_assert_not_reached ("initial connection setup failed");
4148     }
4149 
4150   check1_try_iterations (context, "create_and_hello_sha1",
4151                          check_hello_connection);
4152 
4153   kill_client_connection_unchecked (foo);
4154 
4155   bus_context_unref (context);
4156 
4157   return TRUE;
4158 }
4159 
4160 #endif /* DBUS_BUILD_TESTS */
4161