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