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