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