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