2004-03-16 Richard Hult <richard@imendio.com>
[platform/upstream/dbus.git] / bus / dispatch.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dispatch.c  Message dispatcher
3  *
4  * Copyright (C) 2003  CodeFactory AB
5  * Copyright (C) 2003  Red Hat, Inc.
6  * Copyright (C) 2004  Imendio HB
7  *
8  * Licensed under the Academic Free License version 2.0
9  * 
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  */
25
26 #include "dispatch.h"
27 #include "connection.h"
28 #include "driver.h"
29 #include "services.h"
30 #include "activation.h"
31 #include "utils.h"
32 #include "bus.h"
33 #include "signals.h"
34 #include "test.h"
35 #include <dbus/dbus-internals.h>
36 #include <string.h>
37
38 static dbus_bool_t
39 send_one_message (DBusConnection *connection,
40                   BusContext     *context,
41                   DBusConnection *sender,
42                   DBusConnection *addressed_recipient,
43                   DBusMessage    *message,
44                   BusTransaction *transaction,
45                   DBusError      *error)
46 {
47   if (!bus_context_check_security_policy (context, transaction,
48                                           sender,
49                                           addressed_recipient,
50                                           connection,
51                                           message,
52                                           NULL))
53     return TRUE; /* silently don't send it */
54   
55   if (!bus_transaction_send (transaction,
56                              connection,
57                              message))
58     {
59       BUS_SET_OOM (error);
60       return FALSE;
61     }
62
63   return TRUE;
64 }
65
66 dbus_bool_t
67 bus_dispatch_matches (BusTransaction *transaction,
68                       DBusConnection *sender,
69                       DBusConnection *addressed_recipient,
70                       DBusMessage    *message,
71                       DBusError      *error)
72 {
73   DBusError tmp_error;
74   BusConnections *connections;
75   DBusList *recipients;
76   BusMatchmaker *matchmaker;
77   DBusList *link;
78   BusContext *context;
79
80   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
81
82   /* sender and recipient can both be NULL for the bus driver,
83    * or for signals with no particular recipient
84    */
85
86   _dbus_assert (sender == NULL || bus_connection_is_active (sender));
87   _dbus_assert (dbus_message_get_sender (message) != NULL);
88
89   connections = bus_transaction_get_connections (transaction);
90   
91   dbus_error_init (&tmp_error);
92   context = bus_transaction_get_context (transaction);
93   matchmaker = bus_context_get_matchmaker (context);
94
95   recipients = NULL;
96   if (!bus_matchmaker_get_recipients (matchmaker,
97                                       bus_context_get_connections (context),
98                                       sender, addressed_recipient, message,
99                                       &recipients))
100     {
101       BUS_SET_OOM (error);
102       return FALSE;
103     }
104
105   link = _dbus_list_get_first_link (&recipients);
106   while (link != NULL)
107     {
108       DBusConnection *dest;
109
110       dest = link->data;
111
112       if (!send_one_message (dest, context, sender, addressed_recipient,
113                              message, transaction, &tmp_error))
114         break;
115
116       link = _dbus_list_get_next_link (&recipients, link);
117     }
118
119   _dbus_list_clear (&recipients);
120   
121   if (dbus_error_is_set (&tmp_error))
122     {
123       dbus_move_error (&tmp_error, error);
124       return FALSE;
125     }
126   else
127     return TRUE;
128 }
129
130 static DBusHandlerResult
131 bus_dispatch (DBusConnection *connection,
132               DBusMessage    *message)
133 {
134   const char *sender, *service_name;
135   DBusError error;
136   BusTransaction *transaction;
137   BusContext *context;
138   DBusHandlerResult result;
139   DBusConnection *addressed_recipient;
140   
141   result = DBUS_HANDLER_RESULT_HANDLED;
142   
143   transaction = NULL;
144   addressed_recipient = NULL;
145   dbus_error_init (&error);
146   
147   context = bus_connection_get_context (connection);
148   _dbus_assert (context != NULL);
149   
150   /* If we can't even allocate an OOM error, we just go to sleep
151    * until we can.
152    */
153   while (!bus_connection_preallocate_oom_error (connection))
154     _dbus_wait_for_memory ();
155   
156   /* Ref connection in case we disconnect it at some point in here */
157   dbus_connection_ref (connection);
158   
159   service_name = dbus_message_get_destination (message);
160
161 #ifdef DBUS_ENABLE_VERBOSE_MODE
162   {
163     const char *interface_name, *member_name, *error_name;
164
165     interface_name = dbus_message_get_interface (message);
166     member_name = dbus_message_get_member (message);
167     error_name = dbus_message_get_error_name (message);
168     
169     _dbus_verbose ("DISPATCH: %s %s %s to %s\n",
170                    interface_name ? interface_name : "(no interface)",
171                    member_name ? member_name : "(no member)",
172                    error_name ? error_name : "(no error name)",
173                    service_name ? service_name : "peer");
174   }
175 #endif /* DBUS_ENABLE_VERBOSE_MODE */
176   
177   /* If service_name is NULL, if it's a signal we send it to all
178    * connections with a match rule. If it's not a signal, there
179    * are some special cases here but mostly we just bail out.
180    */
181   if (service_name == NULL)
182     {
183       if (dbus_message_is_signal (message,
184                                   DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
185                                   "Disconnected"))
186         {
187           bus_connection_disconnected (connection);
188           goto out;
189         }
190
191       if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
192         {
193           /* DBusConnection also handles some of these automatically, we leave
194            * it to do so.
195            */
196           result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
197           goto out;
198         }
199     }
200   
201   /* Create our transaction */
202   transaction = bus_transaction_new (context);
203   if (transaction == NULL)
204     {
205       BUS_SET_OOM (&error);
206       goto out;
207     }
208   
209   /* Assign a sender to the message */
210   if (bus_connection_is_active (connection))
211     {
212       sender = bus_connection_get_name (connection);
213       _dbus_assert (sender != NULL);
214
215       if (!dbus_message_set_sender (message, sender))
216         {
217           BUS_SET_OOM (&error);
218           goto out;
219         }
220
221       /* We need to refetch the service name here, because
222        * dbus_message_set_sender can cause the header to be
223        * reallocated, and thus the service_name pointer will become
224        * invalid.
225        */
226       service_name = dbus_message_get_destination (message);
227     }
228   
229   if (service_name &&
230       strcmp (service_name, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0) /* to bus driver */
231     {
232       if (!bus_context_check_security_policy (context, transaction,
233                                               connection, NULL, NULL, message, &error))
234         {
235           _dbus_verbose ("Security policy rejected message\n");
236           goto out;
237         }
238
239       _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
240       if (!bus_driver_handle_message (connection, transaction, message, &error))
241         goto out;
242     }
243   else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
244     {
245       _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
246       dbus_connection_disconnect (connection);
247       goto out;
248     }
249   else if (service_name != NULL) /* route to named service */
250     {
251       DBusString service_string;
252       BusService *service;
253       BusRegistry *registry;
254
255       _dbus_assert (service_name != NULL);
256       
257       registry = bus_connection_get_registry (connection);
258       
259       _dbus_string_init_const (&service_string, service_name);
260       service = bus_registry_lookup (registry, &service_string);
261
262       if (service == NULL && dbus_message_get_auto_activation (message))
263         {
264           BusActivation *activation;
265
266           /* We can't do the security policy check here, since the addressed
267            * recipient service doesn't exist yet. We do it before sending the
268            * message after the service has been created.
269            */
270           activation = bus_connection_get_activation (connection);
271
272           if (!bus_activation_activate_service (activation, connection, transaction, TRUE,
273                                                 message, service_name, &error))
274             {
275               _DBUS_ASSERT_ERROR_IS_SET (&error);
276               _dbus_verbose ("bus_activation_activate_service() failed\n");
277               goto out;
278             }
279           
280           goto out;
281         }
282       else if (service == NULL)
283         {
284           dbus_set_error (&error,
285                           DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
286                           "Service \"%s\" does not exist",
287                           service_name);
288           goto out;
289         }
290       else
291         {          
292           addressed_recipient = bus_service_get_primary_owner (service);
293           _dbus_assert (addressed_recipient != NULL);
294           
295           if (!bus_context_check_security_policy (context, transaction,
296                                                   connection, addressed_recipient,
297                                                   addressed_recipient,
298                                                   message, &error))
299             goto out;
300           
301           /* Dispatch the message */
302           if (!bus_transaction_send (transaction, addressed_recipient, message))
303             {
304               BUS_SET_OOM (&error);
305               goto out;
306             }
307         }
308     }
309
310   /* Now match the messages against any match rules, which will send
311    * out signals and such. addressed_recipient may == NULL.
312    */
313   if (!bus_dispatch_matches (transaction, connection, addressed_recipient, message, &error))
314     goto out;
315   
316  out:
317   if (dbus_error_is_set (&error))
318     {
319       if (!dbus_connection_get_is_connected (connection))
320         {
321           /* If we disconnected it, we won't bother to send it any error
322            * messages.
323            */
324           _dbus_verbose ("Not sending error to connection we disconnected\n");
325         }
326       else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
327         {
328           bus_connection_send_oom_error (connection, message);
329
330           /* cancel transaction due to OOM */
331           if (transaction != NULL)
332             {
333               bus_transaction_cancel_and_free (transaction);
334               transaction = NULL;
335             }
336         }
337       else
338         {
339           /* Try to send the real error, if no mem to do that, send
340            * the OOM error
341            */
342           _dbus_assert (transaction != NULL);
343           
344           if (!bus_transaction_send_error_reply (transaction, connection,
345                                                  &error, message))
346             {
347               bus_connection_send_oom_error (connection, message);
348               
349               /* cancel transaction due to OOM */
350               if (transaction != NULL)
351                 {
352                   bus_transaction_cancel_and_free (transaction);
353                   transaction = NULL;
354                 }
355             }
356         }
357       
358       dbus_error_free (&error);
359     }
360
361   if (transaction != NULL)
362     {
363       bus_transaction_execute_and_free (transaction);
364     }
365
366   dbus_connection_unref (connection);
367
368   return result;
369 }
370
371 static DBusHandlerResult
372 bus_dispatch_message_filter (DBusConnection     *connection,
373                              DBusMessage        *message,
374                              void               *user_data)
375 {
376   return bus_dispatch (connection, message);
377 }
378
379 dbus_bool_t
380 bus_dispatch_add_connection (DBusConnection *connection)
381 {  
382   if (!dbus_connection_add_filter (connection,
383                                    bus_dispatch_message_filter,
384                                    NULL, NULL))
385     return FALSE;
386   
387   return TRUE;
388 }
389
390 void
391 bus_dispatch_remove_connection (DBusConnection *connection)
392 {
393   /* Here we tell the bus driver that we want to get off. */
394   bus_driver_remove_connection (connection);
395
396   dbus_connection_remove_filter (connection,
397                                  bus_dispatch_message_filter,
398                                  NULL);
399 }
400
401 #ifdef DBUS_BUILD_TESTS
402
403 #include <stdio.h>
404
405 typedef dbus_bool_t (* Check1Func) (BusContext     *context);
406 typedef dbus_bool_t (* Check2Func) (BusContext     *context,
407                                     DBusConnection *connection);
408
409 static dbus_bool_t check_no_leftovers (BusContext *context);
410
411 static void
412 block_connection_until_message_from_bus (BusContext     *context,
413                                          DBusConnection *connection)
414 {
415   while (dbus_connection_get_dispatch_status (connection) ==
416          DBUS_DISPATCH_COMPLETE &&
417          dbus_connection_get_is_connected (connection))
418     {
419       bus_test_run_bus_loop (context, TRUE);
420       bus_test_run_clients_loop (FALSE);
421     }
422 }
423
424 /* compensate for fact that pop_message() can return #NULL due to OOM */
425 static DBusMessage*
426 pop_message_waiting_for_memory (DBusConnection *connection)
427 {
428   while (dbus_connection_get_dispatch_status (connection) ==
429          DBUS_DISPATCH_NEED_MEMORY)
430     _dbus_wait_for_memory ();
431
432   return dbus_connection_pop_message (connection);
433 }
434
435 static void
436 warn_unexpected_real (DBusConnection *connection,
437                       DBusMessage    *message,
438                       const char     *expected,
439                       const char     *function,
440                       int             line)
441 {
442   if (message)
443     _dbus_warn ("%s:%d received message interface \"%s\" member \"%s\" error name \"%s\" on %p, expecting %s\n",
444                 function, line,
445                 dbus_message_get_interface (message) ?
446                 dbus_message_get_interface (message) : "(unset)",
447                 dbus_message_get_member (message) ?
448                 dbus_message_get_member (message) : "(unset)",
449                 dbus_message_get_error_name (message) ?
450                 dbus_message_get_error_name (message) : "(unset)",
451                 connection,
452                 expected);
453   else
454     _dbus_warn ("%s:%d received no message on %p, expecting %s\n",
455                 function, line, connection, expected);
456 }
457
458 #define warn_unexpected(connection, message, expected) \
459   warn_unexpected_real (connection, message, expected, _DBUS_FUNCTION_NAME, __LINE__)
460
461 static void
462 verbose_message_received (DBusConnection *connection,
463                           DBusMessage    *message)
464 {
465   _dbus_verbose ("Received message interface \"%s\" member \"%s\" error name \"%s\" on %p\n",
466                  dbus_message_get_interface (message) ?
467                  dbus_message_get_interface (message) : "(unset)",
468                  dbus_message_get_member (message) ?
469                  dbus_message_get_member (message) : "(unset)",
470                  dbus_message_get_error_name (message) ?
471                  dbus_message_get_error_name (message) : "(unset)",
472                  connection);
473 }
474
475 typedef struct
476 {
477   const char *expected_service_name;
478   dbus_bool_t failed;
479 } CheckServiceDeletedData;
480
481 static dbus_bool_t
482 check_service_deleted_foreach (DBusConnection *connection,
483                                void           *data)
484 {
485   CheckServiceDeletedData *d = data;
486   DBusMessage *message;
487   DBusError error;
488   char *service_name;
489
490   dbus_error_init (&error);
491   d->failed = TRUE;
492   service_name = NULL;
493   
494   message = pop_message_waiting_for_memory (connection);
495   if (message == NULL)
496     {
497       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
498                   connection, "ServiceDeleted");
499       goto out;
500     }
501   else if (!dbus_message_is_signal (message,
502                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
503                                     "ServiceDeleted"))
504     {
505       warn_unexpected (connection, message, "ServiceDeleted");
506
507       goto out;
508     }
509   else
510     {
511       if (!dbus_message_get_args (message, &error,
512                                   DBUS_TYPE_STRING, &service_name,
513                                   DBUS_TYPE_INVALID))
514         {
515           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
516             {
517               _dbus_verbose ("no memory to get service name arg\n");
518             }
519           else
520             {
521               _dbus_assert (dbus_error_is_set (&error));
522               _dbus_warn ("Did not get the expected single string argument\n");
523               goto out;
524             }
525         }
526       else if (strcmp (service_name, d->expected_service_name) != 0)
527         {
528           _dbus_warn ("expected deletion of service %s, got deletion of %s\n",
529                       d->expected_service_name,
530                       service_name);
531           goto out;
532         }
533     }
534
535   d->failed = FALSE;
536   
537  out:
538   dbus_free (service_name);
539   dbus_error_free (&error);
540   
541   if (message)
542     dbus_message_unref (message);
543
544   return !d->failed;
545 }
546
547 static void
548 kill_client_connection (BusContext     *context,
549                         DBusConnection *connection)
550 {
551   char *base_service;
552   const char *s;
553   CheckServiceDeletedData csdd;
554
555   _dbus_verbose ("killing connection %p\n", connection);
556   
557   s = dbus_bus_get_base_service (connection);
558   _dbus_assert (s != NULL);
559
560   while ((base_service = _dbus_strdup (s)) == NULL)
561     _dbus_wait_for_memory ();
562
563   dbus_connection_ref (connection);
564   
565   /* kick in the disconnect handler that unrefs the connection */
566   dbus_connection_disconnect (connection);
567
568   bus_test_run_everything (context);
569   
570   _dbus_assert (bus_test_client_listed (connection));
571   
572   /* Run disconnect handler in test.c */
573   if (bus_connection_dispatch_one_message (connection))
574     _dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
575   
576   _dbus_assert (!dbus_connection_get_is_connected (connection));
577   dbus_connection_unref (connection);
578   connection = NULL;
579   _dbus_assert (!bus_test_client_listed (connection));
580   
581   csdd.expected_service_name = base_service;
582   csdd.failed = FALSE;
583
584   bus_test_clients_foreach (check_service_deleted_foreach,
585                             &csdd);
586
587   dbus_free (base_service);
588   
589   if (csdd.failed)
590     _dbus_assert_not_reached ("didn't get the expected ServiceDeleted messages");
591   
592   if (!check_no_leftovers (context))
593     _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
594 }
595
596 static void
597 kill_client_connection_unchecked (DBusConnection *connection)
598 {
599   /* This kills the connection without expecting it to affect
600    * the rest of the bus.
601    */  
602   _dbus_verbose ("Unchecked kill of connection %p\n", connection);
603
604   dbus_connection_ref (connection);
605   dbus_connection_disconnect (connection);
606   /* dispatching disconnect handler will unref once */
607   if (bus_connection_dispatch_one_message (connection))
608     _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
609
610   _dbus_assert (!bus_test_client_listed (connection));
611   dbus_connection_unref (connection);
612 }
613
614 typedef struct
615 {
616   dbus_bool_t failed;
617 } CheckNoMessagesData;
618
619 static dbus_bool_t
620 check_no_messages_foreach (DBusConnection *connection,
621                            void           *data)
622 {
623   CheckNoMessagesData *d = data;
624   DBusMessage *message;
625
626   message = pop_message_waiting_for_memory (connection);
627   if (message != NULL)
628     {
629       warn_unexpected (connection, message, "no messages");
630
631       d->failed = TRUE;
632     }
633
634   if (message)
635     dbus_message_unref (message);
636   return !d->failed;
637 }
638
639 typedef struct
640 {
641   DBusConnection *skip_connection;
642   const char *expected_service_name;
643   dbus_bool_t failed;
644 } CheckServiceCreatedData;
645
646 static dbus_bool_t
647 check_service_created_foreach (DBusConnection *connection,
648                                void           *data)
649 {
650   CheckServiceCreatedData *d = data;
651   DBusMessage *message;
652   DBusError error;
653   char *service_name;
654
655   if (connection == d->skip_connection)
656     return TRUE;
657
658   dbus_error_init (&error);
659   d->failed = TRUE;
660   service_name = NULL;
661   
662   message = pop_message_waiting_for_memory (connection);
663   if (message == NULL)
664     {
665       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
666                   connection, "ServiceCreated");
667       goto out;
668     }
669   else if (!dbus_message_is_signal (message,
670                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
671                                     "ServiceCreated"))
672     {
673       warn_unexpected (connection, message, "ServiceCreated");
674       goto out;
675     }
676   else
677     {
678       if (!dbus_message_get_args (message, &error,
679                                   DBUS_TYPE_STRING, &service_name,
680                                   DBUS_TYPE_INVALID))
681         {
682           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
683             {
684               _dbus_verbose ("no memory to get service name arg\n");
685             }
686           else
687             {
688               _dbus_assert (dbus_error_is_set (&error));
689               _dbus_warn ("Did not get the expected single string argument\n");
690               goto out;
691             }
692         }
693       else if (strcmp (service_name, d->expected_service_name) != 0)
694         {
695           _dbus_warn ("expected creation of service %s, got creation of %s\n",
696                       d->expected_service_name,
697                       service_name);
698           goto out;
699         }
700     }
701
702   d->failed = FALSE;
703   
704  out:
705   dbus_free (service_name);
706   dbus_error_free (&error);
707   
708   if (message)
709     dbus_message_unref (message);
710
711   return !d->failed;
712 }
713
714 static dbus_bool_t
715 check_no_leftovers (BusContext *context)
716 {
717   CheckNoMessagesData nmd;
718
719   nmd.failed = FALSE;
720   bus_test_clients_foreach (check_no_messages_foreach,
721                             &nmd);
722   
723   if (nmd.failed)
724     return FALSE;
725   else
726     return TRUE;
727 }
728
729 /* returns TRUE if the correct thing happens,
730  * but the correct thing may include OOM errors.
731  */
732 static dbus_bool_t
733 check_hello_message (BusContext     *context,
734                      DBusConnection *connection)
735 {
736   DBusMessage *message;
737   dbus_uint32_t serial;
738   dbus_bool_t retval;
739   DBusError error;
740   char *name;
741   char *acquired;
742
743   retval = FALSE;
744   dbus_error_init (&error);
745   name = NULL;
746   acquired = NULL;
747   message = NULL;
748
749   _dbus_verbose ("check_hello_message for %p\n", connection);
750   
751   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
752                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
753                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
754                                           "Hello");
755
756   if (message == NULL)
757     return TRUE;
758
759   if (!dbus_connection_send (connection, message, &serial))
760     {
761       dbus_message_unref (message);
762       return TRUE;
763     }
764
765   dbus_message_unref (message);
766   message = NULL;
767
768   /* send our message */
769   bus_test_run_clients_loop (TRUE);
770
771   dbus_connection_ref (connection); /* because we may get disconnected */
772   block_connection_until_message_from_bus (context, connection);
773
774   if (!dbus_connection_get_is_connected (connection))
775     {
776       _dbus_verbose ("connection was disconnected\n");
777       
778       dbus_connection_unref (connection);
779       
780       return TRUE;
781     }
782
783   dbus_connection_unref (connection);
784   
785   message = pop_message_waiting_for_memory (connection);
786   if (message == NULL)
787     {
788       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
789                   "Hello", serial, connection);
790       goto out;
791     }
792
793   verbose_message_received (connection, message);
794
795   if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
796     {
797       _dbus_warn ("Message has wrong sender %s\n",
798                   dbus_message_get_sender (message) ?
799                   dbus_message_get_sender (message) : "(none)");
800       goto out;
801     }
802   
803   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
804     {
805       if (dbus_message_is_error (message,
806                                  DBUS_ERROR_NO_MEMORY))
807         {
808           ; /* good, this is a valid response */
809         }
810       else
811         {
812           warn_unexpected (connection, message, "not this error");
813
814           goto out;
815         }
816     }
817   else
818     {
819       CheckServiceCreatedData scd;
820       
821       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
822         {
823           ; /* good, expected */
824         }
825       else
826         {
827           warn_unexpected (connection, message, "method return for Hello");
828
829           goto out;
830         }
831
832     retry_get_hello_name:
833       if (!dbus_message_get_args (message, &error,
834                                   DBUS_TYPE_STRING, &name,
835                                   DBUS_TYPE_INVALID))
836         {
837           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
838             {
839               _dbus_verbose ("no memory to get service name arg from hello\n");
840               dbus_error_free (&error);
841               _dbus_wait_for_memory ();
842               goto retry_get_hello_name;
843             }
844           else
845             {
846               _dbus_assert (dbus_error_is_set (&error));
847               _dbus_warn ("Did not get the expected single string argument to hello\n");
848               goto out;
849             }
850         }
851
852       _dbus_verbose ("Got hello name: %s\n", name);
853
854       while (!dbus_bus_set_base_service (connection, name))
855         _dbus_wait_for_memory ();
856       
857       scd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
858       scd.failed = FALSE;
859       scd.expected_service_name = name;
860       bus_test_clients_foreach (check_service_created_foreach,
861                                 &scd);
862       
863       if (scd.failed)
864         goto out;
865       
866       /* Client should also have gotten ServiceAcquired */
867       dbus_message_unref (message);
868       message = pop_message_waiting_for_memory (connection);
869       if (message == NULL)
870         {
871           _dbus_warn ("Expecting %s, got nothing\n",
872                       "ServiceAcquired");
873           goto out;
874         }
875       
876     retry_get_acquired_name:
877       if (!dbus_message_get_args (message, &error,
878                                   DBUS_TYPE_STRING, &acquired,
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 acquired\n");
884               dbus_error_free (&error);
885               _dbus_wait_for_memory ();
886               goto retry_get_acquired_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 ServiceAcquired\n");
892               goto out;
893             }
894         }
895
896       _dbus_verbose ("Got acquired name: %s\n", acquired);
897
898       if (strcmp (acquired, name) != 0)
899         {
900           _dbus_warn ("Acquired name is %s but expected %s\n",
901                       acquired, name);
902           goto out;
903         }
904     }
905
906   if (!check_no_leftovers (context))
907     goto out;
908   
909   retval = TRUE;
910   
911  out:
912   dbus_error_free (&error);
913   
914   dbus_free (name);
915   dbus_free (acquired);
916   
917   if (message)
918     dbus_message_unref (message);
919   
920   return retval;
921 }
922
923 /* returns TRUE if the correct thing happens,
924  * but the correct thing may include OOM errors.
925  */
926 static dbus_bool_t
927 check_add_match_all (BusContext     *context,
928                      DBusConnection *connection)
929 {
930   DBusMessage *message;
931   dbus_bool_t retval;
932   dbus_uint32_t serial;
933   DBusError error;
934
935   retval = FALSE;
936   dbus_error_init (&error);
937   message = NULL;
938
939   _dbus_verbose ("check_add_match_all for %p\n", connection);
940   
941   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
942                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
943                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
944                                           "AddMatch");
945
946   if (message == NULL)
947     return TRUE;
948
949   /* empty string match rule matches everything */
950   if (!dbus_message_append_args (message, DBUS_TYPE_STRING, "",
951                                  DBUS_TYPE_INVALID))
952     {
953       dbus_message_unref (message);
954       return TRUE;
955     }
956   
957   if (!dbus_connection_send (connection, message, &serial))
958     {
959       dbus_message_unref (message);
960       return TRUE;
961     }
962
963   dbus_message_unref (message);
964   message = NULL;
965
966   /* send our message */
967   bus_test_run_clients_loop (TRUE);
968
969   dbus_connection_ref (connection); /* because we may get disconnected */
970   block_connection_until_message_from_bus (context, connection);
971
972   if (!dbus_connection_get_is_connected (connection))
973     {
974       _dbus_verbose ("connection was disconnected\n");
975       
976       dbus_connection_unref (connection);
977       
978       return TRUE;
979     }
980
981   dbus_connection_unref (connection);
982   
983   message = pop_message_waiting_for_memory (connection);
984   if (message == NULL)
985     {
986       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
987                   "AddMatch", serial, connection);
988       goto out;
989     }
990
991   verbose_message_received (connection, message);
992
993   if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
994     {
995       _dbus_warn ("Message has wrong sender %s\n",
996                   dbus_message_get_sender (message) ?
997                   dbus_message_get_sender (message) : "(none)");
998       goto out;
999     }
1000   
1001   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1002     {
1003       if (dbus_message_is_error (message,
1004                                  DBUS_ERROR_NO_MEMORY))
1005         {
1006           ; /* good, this is a valid response */
1007         }
1008       else
1009         {
1010           warn_unexpected (connection, message, "not this error");
1011
1012           goto out;
1013         }
1014     }
1015   else
1016     {
1017       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1018         {
1019           ; /* good, expected */
1020           _dbus_assert (dbus_message_get_reply_serial (message) == serial);
1021         }
1022       else
1023         {
1024           warn_unexpected (connection, message, "method return for AddMatch");
1025
1026           goto out;
1027         }
1028     }
1029
1030   if (!check_no_leftovers (context))
1031     goto out;
1032   
1033   retval = TRUE;
1034   
1035  out:
1036   dbus_error_free (&error);
1037   
1038   if (message)
1039     dbus_message_unref (message);
1040   
1041   return retval;
1042 }
1043
1044 /* returns TRUE if the correct thing happens,
1045  * but the correct thing may include OOM errors.
1046  */
1047 static dbus_bool_t
1048 check_hello_connection (BusContext *context)
1049 {
1050   DBusConnection *connection;
1051   DBusError error;
1052
1053   dbus_error_init (&error);
1054
1055   connection = dbus_connection_open ("debug-pipe:name=test-server", &error);
1056   if (connection == NULL)
1057     {
1058       _DBUS_ASSERT_ERROR_IS_SET (&error);
1059       dbus_error_free (&error);
1060       return TRUE;
1061     }
1062
1063   if (!bus_setup_debug_client (connection))
1064     {
1065       dbus_connection_disconnect (connection);
1066       dbus_connection_unref (connection);
1067       return TRUE;
1068     }
1069
1070   if (!check_hello_message (context, connection))
1071     return FALSE;
1072   
1073   if (dbus_bus_get_base_service (connection) == NULL)
1074     {
1075       /* We didn't successfully register, so we can't
1076        * do the usual kill_client_connection() checks
1077        */
1078       kill_client_connection_unchecked (connection);
1079     }
1080   else
1081     {
1082       if (!check_add_match_all (context, connection))
1083         return FALSE;
1084       
1085       kill_client_connection (context, connection);
1086     }
1087
1088   return TRUE;
1089 }
1090
1091 #define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
1092
1093 /* returns TRUE if the correct thing happens,
1094  * but the correct thing may include OOM errors.
1095  */
1096 static dbus_bool_t
1097 check_nonexistent_service_activation (BusContext     *context,
1098                                       DBusConnection *connection)
1099 {
1100   DBusMessage *message;
1101   dbus_uint32_t serial;
1102   dbus_bool_t retval;
1103   DBusError error;
1104   
1105   dbus_error_init (&error);
1106   
1107   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
1108                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
1109                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
1110                                           "ActivateService");
1111
1112   if (message == NULL)
1113     return TRUE;
1114
1115   if (!dbus_message_append_args (message,
1116                                  DBUS_TYPE_STRING, NONEXISTENT_SERVICE_NAME,
1117                                  DBUS_TYPE_UINT32, 0,
1118                                  DBUS_TYPE_INVALID))
1119     {
1120       dbus_message_unref (message);
1121       return TRUE;
1122     }
1123   
1124   if (!dbus_connection_send (connection, message, &serial))
1125     {
1126       dbus_message_unref (message);
1127       return TRUE;
1128     }
1129
1130   dbus_message_unref (message);
1131   message = NULL;
1132
1133   bus_test_run_everything (context);
1134   block_connection_until_message_from_bus (context, connection);
1135   bus_test_run_everything (context);
1136
1137   if (!dbus_connection_get_is_connected (connection))
1138     {
1139       _dbus_verbose ("connection was disconnected\n");
1140       return TRUE;
1141     }
1142   
1143   retval = FALSE;
1144   
1145   message = pop_message_waiting_for_memory (connection);
1146   if (message == NULL)
1147     {
1148       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1149                   "ActivateService", serial, connection);
1150       goto out;
1151     }
1152
1153   verbose_message_received (connection, message);
1154
1155   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1156     {
1157       if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
1158         {
1159           _dbus_warn ("Message has wrong sender %s\n",
1160                       dbus_message_get_sender (message) ?
1161                       dbus_message_get_sender (message) : "(none)");
1162           goto out;
1163         }
1164       
1165       if (dbus_message_is_error (message,
1166                                  DBUS_ERROR_NO_MEMORY))
1167         {
1168           ; /* good, this is a valid response */
1169         }
1170       else if (dbus_message_is_error (message,
1171                                       DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1172         {
1173           ; /* good, this is expected also */
1174         }
1175       else
1176         {
1177           warn_unexpected (connection, message, "not this error");
1178           goto out;
1179         }
1180     }
1181   else
1182     {
1183       _dbus_warn ("Did not expect to successfully activate %s\n",
1184                   NONEXISTENT_SERVICE_NAME);
1185       goto out;
1186     }
1187
1188   retval = TRUE;
1189   
1190  out:
1191   if (message)
1192     dbus_message_unref (message);
1193   
1194   return retval;
1195 }
1196
1197 /* returns TRUE if the correct thing happens,
1198  * but the correct thing may include OOM errors.
1199  */
1200 static dbus_bool_t
1201 check_nonexistent_service_auto_activation (BusContext     *context,
1202                                            DBusConnection *connection)
1203 {
1204   DBusMessage *message;
1205   dbus_uint32_t serial;
1206   dbus_bool_t retval;
1207   DBusError error;
1208     
1209   dbus_error_init (&error);
1210
1211   message = dbus_message_new_method_call (NONEXISTENT_SERVICE_NAME,
1212                                           "/org/freedesktop/TestSuite",
1213                                           "org.freedesktop.TestSuite",
1214                                           "Echo");
1215   
1216   if (message == NULL)
1217     return TRUE;
1218
1219   dbus_message_set_auto_activation (message, TRUE);
1220  
1221   if (!dbus_connection_send (connection, message, &serial))
1222     {
1223       dbus_message_unref (message);
1224       return TRUE;
1225     }
1226
1227   dbus_message_unref (message);
1228   message = NULL;
1229
1230   bus_test_run_everything (context);
1231   block_connection_until_message_from_bus (context, connection);
1232   bus_test_run_everything (context);
1233
1234   if (!dbus_connection_get_is_connected (connection))
1235     {
1236       _dbus_verbose ("connection was disconnected\n");
1237       return TRUE;
1238     }
1239   
1240   retval = FALSE;
1241   
1242   message = pop_message_waiting_for_memory (connection);
1243
1244   if (message == NULL)
1245     {
1246       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1247                   "Echo message (auto activation)", serial, connection);
1248       goto out;
1249     }
1250
1251   verbose_message_received (connection, message);
1252
1253   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1254     {
1255       if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
1256         {
1257           _dbus_warn ("Message has wrong sender %s\n",
1258                       dbus_message_get_sender (message) ?
1259                       dbus_message_get_sender (message) : "(none)");
1260           goto out;
1261         }
1262       
1263       if (dbus_message_is_error (message,
1264                                  DBUS_ERROR_NO_MEMORY))
1265         {
1266           ; /* good, this is a valid response */
1267         }
1268       else if (dbus_message_is_error (message,
1269                                       DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1270         {
1271           ; /* good, this is expected also */
1272         }
1273       else
1274         {
1275           warn_unexpected (connection, message, "not this error");
1276           goto out;
1277         }
1278     }
1279   else
1280     {
1281       _dbus_warn ("Did not expect to successfully activate %s\n",
1282                   NONEXISTENT_SERVICE_NAME);
1283       goto out;
1284     }
1285
1286   retval = TRUE;
1287   
1288  out:
1289   if (message)
1290     dbus_message_unref (message);
1291   
1292   return retval;
1293 }
1294
1295 static dbus_bool_t
1296 check_base_service_activated (BusContext     *context,
1297                               DBusConnection *connection,
1298                               DBusMessage    *initial_message,
1299                               char          **base_service_p)
1300 {
1301   DBusMessage *message;
1302   dbus_bool_t retval;
1303   DBusError error;
1304   char *base_service;
1305   
1306   base_service = NULL;
1307   retval = FALSE;
1308   
1309   dbus_error_init (&error);
1310
1311   message = initial_message;
1312   dbus_message_ref (message);  
1313
1314   if (dbus_message_is_signal (message,
1315                               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
1316                               "ServiceCreated"))
1317     {
1318       char *service_name;
1319       CheckServiceCreatedData scd;
1320
1321     reget_service_name_arg:
1322       if (!dbus_message_get_args (message, &error,
1323                                   DBUS_TYPE_STRING, &service_name,
1324                                   DBUS_TYPE_INVALID))
1325         {
1326           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1327             {
1328               dbus_error_free (&error);
1329               _dbus_wait_for_memory ();
1330               goto reget_service_name_arg;
1331             }
1332           else
1333             {
1334               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1335                           "ServiceCreated",
1336                           error.message);
1337               dbus_error_free (&error);
1338               goto out;
1339             }
1340         }
1341
1342       if (*service_name != ':')
1343         {
1344           _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
1345                       service_name);
1346           goto out;
1347         }
1348               
1349       base_service = service_name;
1350       service_name = NULL;
1351       
1352       scd.skip_connection = connection;
1353       scd.failed = FALSE;
1354       scd.expected_service_name = base_service;
1355       bus_test_clients_foreach (check_service_created_foreach,
1356                                 &scd);
1357       
1358       if (scd.failed)
1359         goto out;
1360     }
1361   else
1362     {
1363       warn_unexpected (connection, message, "ServiceCreated for base service");
1364
1365       goto out;
1366     }
1367
1368   retval = TRUE;
1369
1370   if (base_service_p)
1371     {
1372       *base_service_p = base_service;
1373       base_service = NULL;
1374     }
1375   
1376  out:
1377   if (message)
1378     dbus_message_unref (message);
1379
1380   if (base_service)
1381     dbus_free (base_service);
1382   
1383   return retval;
1384 }
1385
1386 static dbus_bool_t
1387 check_service_activated (BusContext     *context,
1388                          DBusConnection *connection,
1389                          const char     *activated_name,
1390                          const char     *base_service_name,
1391                          DBusMessage    *initial_message)
1392 {
1393   DBusMessage *message;
1394   dbus_bool_t retval;
1395   DBusError error;
1396   dbus_uint32_t activation_result;
1397   
1398   retval = FALSE;
1399   
1400   dbus_error_init (&error);
1401
1402   message = initial_message;
1403   dbus_message_ref (message);
1404
1405   if (dbus_message_is_signal (message,
1406                               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
1407                               "ServiceCreated"))
1408     {
1409       char *service_name;
1410       CheckServiceCreatedData scd;
1411
1412     reget_service_name_arg:
1413       if (!dbus_message_get_args (message, &error,
1414                                   DBUS_TYPE_STRING, &service_name,
1415                                   DBUS_TYPE_INVALID))
1416         {
1417           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1418             {
1419               dbus_error_free (&error);
1420               _dbus_wait_for_memory ();
1421               goto reget_service_name_arg;
1422             }
1423           else
1424             {
1425               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1426                           "ServiceCreated",
1427                           error.message);
1428               dbus_error_free (&error);
1429               goto out;
1430             }
1431         }
1432
1433       if (strcmp (service_name, activated_name) != 0)
1434         {
1435           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
1436                       activated_name, service_name);
1437           dbus_free (service_name);
1438           goto out;
1439         }
1440       
1441       scd.skip_connection = connection;
1442       scd.failed = FALSE;
1443       scd.expected_service_name = service_name;
1444       bus_test_clients_foreach (check_service_created_foreach,
1445                                 &scd);
1446           
1447       dbus_free (service_name);
1448
1449       if (scd.failed)
1450         goto out;
1451           
1452       dbus_message_unref (message);
1453       message = pop_message_waiting_for_memory (connection);
1454       if (message == NULL)
1455         {
1456           _dbus_warn ("Expected a reply to %s, got nothing\n",
1457                       "ActivateService");
1458           goto out;
1459         }
1460     }
1461   else
1462     {
1463       warn_unexpected (connection, message, "ServiceCreated for the activated name");
1464       
1465       goto out;
1466     }
1467   
1468   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
1469     {
1470       warn_unexpected (connection, message, "reply to ActivateService");
1471
1472       goto out;
1473     }
1474
1475   activation_result = 0;
1476   if (!dbus_message_get_args (message, &error,
1477                               DBUS_TYPE_UINT32, &activation_result,
1478                               DBUS_TYPE_INVALID))
1479     {
1480       if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1481         {
1482           _dbus_warn ("Did not have activation result first argument to %s: %s\n",
1483                       "ActivateService", error.message);
1484           dbus_error_free (&error);
1485           goto out;
1486         }
1487
1488       dbus_error_free (&error);
1489     }
1490   else
1491     {
1492       if (activation_result == DBUS_ACTIVATION_REPLY_ACTIVATED)
1493         ; /* Good */
1494       else if (activation_result == DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE)
1495         ; /* Good also */
1496       else
1497         {
1498           _dbus_warn ("Activation result was 0x%x, no good.\n",
1499                       activation_result);
1500           goto out;
1501         }
1502     }
1503
1504   dbus_message_unref (message);
1505   message = NULL;
1506       
1507   if (!check_no_leftovers (context))
1508     {
1509       _dbus_warn ("Messages were left over after verifying existent activation results\n");
1510       goto out;
1511     }
1512
1513   retval = TRUE;
1514   
1515  out:
1516   if (message)
1517     dbus_message_unref (message);
1518   
1519   return retval;
1520 }
1521
1522 static dbus_bool_t
1523 check_service_auto_activated (BusContext     *context,
1524                               DBusConnection *connection,
1525                               const char     *activated_name,
1526                               const char     *base_service_name,
1527                               DBusMessage    *initial_message)
1528 {
1529   DBusMessage *message;
1530   dbus_bool_t retval;
1531   DBusError error;
1532   
1533   retval = FALSE;
1534   
1535   dbus_error_init (&error);
1536
1537   message = initial_message;
1538   dbus_message_ref (message);
1539
1540   if (dbus_message_is_signal (message,
1541                               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
1542                               "ServiceCreated"))
1543     {
1544       char *service_name;
1545       CheckServiceCreatedData scd;
1546       
1547     reget_service_name_arg:
1548       if (!dbus_message_get_args (message, &error,
1549                                   DBUS_TYPE_STRING, &service_name,
1550                                   DBUS_TYPE_INVALID))
1551         {
1552           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1553             {
1554               dbus_error_free (&error);
1555               _dbus_wait_for_memory ();
1556               goto reget_service_name_arg;
1557             }
1558           else
1559             {
1560               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1561                           "ServiceCreated",
1562                           error.message);
1563               dbus_error_free (&error);
1564               goto out;
1565             }
1566         }
1567       
1568       if (strcmp (service_name, activated_name) != 0)
1569         {
1570           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
1571                       activated_name, service_name);
1572           dbus_free (service_name);
1573           goto out;
1574         }
1575       
1576       scd.skip_connection = connection;
1577       scd.failed = FALSE;
1578       scd.expected_service_name = service_name;
1579       bus_test_clients_foreach (check_service_created_foreach,
1580                                 &scd);
1581       
1582       dbus_free (service_name);
1583       
1584       if (scd.failed)
1585         goto out;
1586       
1587       /* Note that this differs from regular activation in that we don't get a
1588        * reply to ActivateService here.
1589        */
1590       
1591       dbus_message_unref (message);
1592       message = NULL;
1593     }
1594   else
1595     {
1596       warn_unexpected (connection, message, "ServiceCreated for the activated name");
1597       
1598       goto out;
1599     }
1600   
1601   retval = TRUE;
1602   
1603  out:
1604   if (message)
1605     dbus_message_unref (message);
1606   
1607   return retval;
1608 }
1609
1610 static dbus_bool_t
1611 check_service_deactivated (BusContext     *context,
1612                            DBusConnection *connection,
1613                            const char     *activated_name,
1614                            const char     *base_service)
1615 {
1616   DBusMessage *message;
1617   dbus_bool_t retval;
1618   DBusError error;
1619   CheckServiceDeletedData csdd;
1620
1621   message = NULL;
1622   retval = FALSE;
1623   
1624   dbus_error_init (&error);
1625
1626   /* Now we are expecting ServiceDeleted messages for the base
1627    * service and the activated_name.  The base service
1628    * notification is required to come last.
1629    */
1630   csdd.expected_service_name = activated_name;
1631   csdd.failed = FALSE;
1632   bus_test_clients_foreach (check_service_deleted_foreach,
1633                             &csdd);      
1634
1635   if (csdd.failed)
1636     goto out;
1637       
1638   csdd.expected_service_name = base_service;
1639   csdd.failed = FALSE;
1640   bus_test_clients_foreach (check_service_deleted_foreach,
1641                             &csdd);
1642
1643   if (csdd.failed)
1644     goto out;
1645
1646   retval = TRUE;
1647   
1648  out:
1649   if (message)
1650     dbus_message_unref (message);
1651   
1652   return retval;
1653 }
1654
1655 static dbus_bool_t
1656 check_send_exit_to_service (BusContext     *context,
1657                             DBusConnection *connection,
1658                             const char     *service_name,
1659                             const char     *base_service)
1660 {
1661   dbus_bool_t got_error;
1662   DBusMessage *message;
1663   dbus_uint32_t serial;
1664   dbus_bool_t retval;
1665   
1666   _dbus_verbose ("Sending exit message to the test service\n");
1667
1668   retval = FALSE;
1669   
1670   /* Kill off the test service by sending it a quit message */
1671   message = dbus_message_new_method_call (service_name,
1672                                           "/org/freedesktop/TestSuite",
1673                                           "org.freedesktop.TestSuite",
1674                                           "Exit");
1675       
1676   if (message == NULL)
1677     {
1678       /* Do this again; we still need the service to exit... */
1679       if (!check_send_exit_to_service (context, connection,
1680                                        service_name, base_service))
1681         goto out;
1682       
1683       return TRUE;
1684     }
1685       
1686   if (!dbus_connection_send (connection, message, &serial))
1687     {
1688       dbus_message_unref (message);
1689
1690       /* Do this again; we still need the service to exit... */
1691       if (!check_send_exit_to_service (context, connection,
1692                                        service_name, base_service))
1693         goto out;
1694       
1695       return TRUE;
1696     }
1697
1698   dbus_message_unref (message);
1699   message = NULL;
1700
1701   /* send message */
1702   bus_test_run_clients_loop (TRUE);
1703
1704   /* read it in and write it out to test service */
1705   bus_test_run_bus_loop (context, FALSE);
1706
1707   /* see if we got an error during message bus dispatching */
1708   bus_test_run_clients_loop (FALSE);
1709   message = dbus_connection_borrow_message (connection);
1710   got_error = message != NULL && dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
1711   if (message)
1712     {
1713       dbus_connection_return_message (connection, message);
1714       message = NULL;
1715     }
1716           
1717   if (!got_error)
1718     {
1719       /* If no error, wait for the test service to exit */
1720       block_connection_until_message_from_bus (context, connection);
1721               
1722       bus_test_run_everything (context);
1723     }
1724
1725   if (got_error)
1726     {
1727       message = pop_message_waiting_for_memory (connection);
1728       _dbus_assert (message != NULL);
1729
1730       if (dbus_message_get_reply_serial (message) != serial)
1731         {
1732           warn_unexpected (connection, message,
1733                            "error with the correct reply serial");
1734           goto out;
1735         }
1736       
1737       if (!dbus_message_is_error (message,
1738                                   DBUS_ERROR_NO_MEMORY))
1739         {
1740           warn_unexpected (connection, message,
1741                            "a no memory error from asking test service to exit");
1742           goto out;
1743         }
1744
1745       _dbus_verbose ("Got error %s when asking test service to exit\n",
1746                      dbus_message_get_error_name (message));
1747
1748       /* Do this again; we still need the service to exit... */
1749       if (!check_send_exit_to_service (context, connection,
1750                                        service_name, base_service))
1751         goto out;
1752     }
1753   else
1754     {
1755       if (!check_service_deactivated (context, connection,
1756                                       service_name, base_service))
1757         goto out;
1758
1759       /* Should now have a NoReply error from the Exit() method
1760        * call; it should have come after all the deactivation
1761        * stuff.
1762        */
1763       message = pop_message_waiting_for_memory (connection);
1764           
1765       if (message == NULL)
1766         {
1767           warn_unexpected (connection, NULL,
1768                            "reply to Exit() method call");
1769           goto out;
1770         }
1771       if (!dbus_message_is_error (message,
1772                                   DBUS_ERROR_NO_REPLY))
1773         {
1774           warn_unexpected (connection, NULL,
1775                            "NoReply error from Exit() method call");
1776           goto out;
1777         }
1778
1779       if (dbus_message_get_reply_serial (message) != serial)
1780         {
1781           warn_unexpected (connection, message,
1782                            "error with the correct reply serial");
1783           goto out;
1784         }
1785           
1786       _dbus_verbose ("Got error %s after test service exited\n",
1787                      dbus_message_get_error_name (message));
1788       
1789       if (!check_no_leftovers (context))
1790         {
1791           _dbus_warn ("Messages were left over after %s\n",
1792                       _DBUS_FUNCTION_NAME);
1793           goto out;
1794         }
1795     }
1796   
1797   retval = TRUE;
1798   
1799  out:
1800   if (message)
1801     dbus_message_unref (message);
1802   
1803   return retval;
1804 }
1805
1806 static dbus_bool_t
1807 check_got_error (BusContext     *context,
1808                  DBusConnection *connection,
1809                  const char     *first_error_name,
1810                  ...)
1811 {
1812   DBusMessage *message;
1813   dbus_bool_t retval;
1814   va_list ap;
1815   dbus_bool_t error_found;
1816   const char *error_name;
1817   
1818   retval = FALSE;
1819   
1820   message = pop_message_waiting_for_memory (connection);
1821   if (message == NULL)
1822     {
1823       _dbus_warn ("Did not get an expected error\n");
1824       goto out;
1825     }
1826
1827   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
1828     {
1829       warn_unexpected (connection, message, "an error");
1830
1831       goto out;
1832     }
1833
1834   error_found = FALSE;
1835
1836   va_start (ap, first_error_name);
1837   error_name = first_error_name;
1838   while (error_name != NULL)
1839     {
1840       if (dbus_message_is_error (message, error_name))
1841         {
1842           error_found = TRUE;
1843           break;
1844         }
1845       error_name = va_arg (ap, char*);
1846     }
1847   va_end (ap);
1848
1849   if (!error_found)
1850     {
1851       _dbus_warn ("Expected error %s or other, got %s instead\n",
1852                   first_error_name,
1853                   dbus_message_get_error_name (message));
1854       goto out;
1855     }
1856
1857   retval = TRUE;
1858   
1859  out:
1860   if (message)
1861     dbus_message_unref (message);
1862   
1863   return retval;
1864 }
1865           
1866 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
1867
1868 /* returns TRUE if the correct thing happens,
1869  * but the correct thing may include OOM errors.
1870  */
1871 static dbus_bool_t
1872 check_existent_service_activation (BusContext     *context,
1873                                    DBusConnection *connection)
1874 {
1875   DBusMessage *message;
1876   dbus_uint32_t serial;
1877   dbus_bool_t retval;
1878   DBusError error;
1879   char *base_service;
1880
1881   base_service = NULL;
1882   
1883   dbus_error_init (&error);
1884   
1885   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
1886                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
1887                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
1888                                           "ActivateService");
1889
1890   if (message == NULL)
1891     return TRUE;
1892
1893   if (!dbus_message_append_args (message,
1894                                  DBUS_TYPE_STRING, EXISTENT_SERVICE_NAME,
1895                                  DBUS_TYPE_UINT32, 0,
1896                                  DBUS_TYPE_INVALID))
1897     {
1898       dbus_message_unref (message);
1899       return TRUE;
1900     }
1901   
1902   if (!dbus_connection_send (connection, message, &serial))
1903     {
1904       dbus_message_unref (message);
1905       return TRUE;
1906     }
1907
1908   dbus_message_unref (message);
1909   message = NULL;
1910
1911   bus_test_run_everything (context);
1912
1913   /* now wait for the message bus to hear back from the activated
1914    * service.
1915    */
1916   block_connection_until_message_from_bus (context, connection);
1917
1918   bus_test_run_everything (context);
1919
1920   if (!dbus_connection_get_is_connected (connection))
1921     {
1922       _dbus_verbose ("connection was disconnected\n");
1923       return TRUE;
1924     }
1925   
1926   retval = FALSE;
1927   
1928   message = pop_message_waiting_for_memory (connection);
1929   if (message == NULL)
1930     {
1931       _dbus_warn ("Did not receive any messages after %s %d on %p\n",
1932                   "ActivateService", serial, connection);
1933       goto out;
1934     }
1935
1936   verbose_message_received (connection, message);
1937   _dbus_verbose ("  (after sending %s)\n", "ActivateService");
1938
1939   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1940     {
1941       if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
1942         {
1943           _dbus_warn ("Message has wrong sender %s\n",
1944                       dbus_message_get_sender (message) ?
1945                       dbus_message_get_sender (message) : "(none)");
1946           goto out;
1947         }
1948       
1949       if (dbus_message_is_error (message,
1950                                  DBUS_ERROR_NO_MEMORY))
1951         {
1952           ; /* good, this is a valid response */
1953         }
1954       else if (dbus_message_is_error (message,
1955                                       DBUS_ERROR_SPAWN_CHILD_EXITED))
1956         {
1957           ; /* good, this is expected also */
1958         }
1959       else
1960         {
1961           _dbus_warn ("Did not expect error %s\n",
1962                       dbus_message_get_error_name (message));
1963           goto out;
1964         }
1965     }
1966   else
1967     {
1968       dbus_bool_t got_service_deleted;
1969       dbus_bool_t got_error;
1970       
1971       if (!check_base_service_activated (context, connection,
1972                                          message, &base_service))
1973         goto out;
1974
1975       dbus_message_unref (message);
1976       message = NULL;
1977
1978       /* We may need to block here for the test service to exit or finish up */
1979       block_connection_until_message_from_bus (context, connection);
1980       
1981       message = dbus_connection_borrow_message (connection);
1982       if (message == NULL)
1983         {
1984           _dbus_warn ("Did not receive any messages after base service creation notification\n");
1985           goto out;
1986         }
1987
1988       got_service_deleted = dbus_message_is_signal (message,
1989                                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
1990                                                     "ServiceDeleted");
1991       got_error = dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
1992       
1993       dbus_connection_return_message (connection, message);
1994       message = NULL;
1995
1996       if (got_error)
1997         {
1998           if (!check_got_error (context, connection,
1999                                 DBUS_ERROR_SPAWN_CHILD_EXITED,
2000                                 DBUS_ERROR_NO_MEMORY,
2001                                 NULL))
2002             goto out;
2003
2004           /* A service deleted should be coming along now after this error.
2005            * We can also get the error *after* the service deleted.
2006            */
2007           got_service_deleted = TRUE;
2008         }
2009       
2010       if (got_service_deleted)
2011         {
2012           /* The service started up and got a base address, but then
2013            * failed to register under EXISTENT_SERVICE_NAME
2014            */
2015           CheckServiceDeletedData csdd;
2016           
2017           csdd.expected_service_name = base_service;
2018           csdd.failed = FALSE;
2019           bus_test_clients_foreach (check_service_deleted_foreach,
2020                                     &csdd);
2021
2022           if (csdd.failed)
2023             goto out;
2024
2025           /* Now we should get an error about the service exiting
2026            * if we didn't get it before.
2027            */
2028           if (!got_error)
2029             {
2030               block_connection_until_message_from_bus (context, connection);
2031               
2032               /* and process everything again */
2033               bus_test_run_everything (context);
2034               
2035               if (!check_got_error (context, connection,
2036                                     DBUS_ERROR_SPAWN_CHILD_EXITED,
2037                                     NULL))
2038                 goto out;
2039             }
2040         }
2041       else
2042         {
2043           message = pop_message_waiting_for_memory (connection);
2044           if (message == NULL)
2045             {
2046               _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
2047               goto out;
2048             }
2049           
2050           if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
2051                                         base_service, message))
2052             goto out;
2053           
2054           dbus_message_unref (message);
2055           message = NULL;
2056
2057
2058           if (!check_no_leftovers (context))
2059             {
2060               _dbus_warn ("Messages were left over after successful activation\n");
2061               goto out;
2062             }
2063
2064           if (!check_send_exit_to_service (context, connection,
2065                                            EXISTENT_SERVICE_NAME, base_service))
2066             goto out;
2067         }
2068     }
2069   
2070   retval = TRUE;
2071   
2072  out:
2073   if (message)
2074     dbus_message_unref (message);
2075
2076   if (base_service)
2077     dbus_free (base_service);
2078   
2079   return retval;
2080 }
2081
2082 /* returns TRUE if the correct thing happens,
2083  * but the correct thing may include OOM errors.
2084  */
2085 static dbus_bool_t
2086 check_segfault_service_activation (BusContext     *context,
2087                                    DBusConnection *connection)
2088 {
2089   DBusMessage *message;
2090   dbus_uint32_t serial;
2091   dbus_bool_t retval;
2092   DBusError error;
2093   
2094   dbus_error_init (&error);
2095   
2096   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
2097                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
2098                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
2099                                           "ActivateService");
2100
2101   if (message == NULL)
2102     return TRUE;
2103
2104   if (!dbus_message_append_args (message,
2105                                  DBUS_TYPE_STRING,
2106                                  "org.freedesktop.DBus.TestSuiteSegfaultService",
2107                                  DBUS_TYPE_UINT32, 0,
2108                                  DBUS_TYPE_INVALID))
2109     {
2110       dbus_message_unref (message);
2111       return TRUE;
2112     }
2113   
2114   if (!dbus_connection_send (connection, message, &serial))
2115     {
2116       dbus_message_unref (message);
2117       return TRUE;
2118     }
2119
2120   dbus_message_unref (message);
2121   message = NULL;
2122
2123   bus_test_run_everything (context);
2124   block_connection_until_message_from_bus (context, connection);
2125   bus_test_run_everything (context);
2126
2127   if (!dbus_connection_get_is_connected (connection))
2128     {
2129       _dbus_verbose ("connection was disconnected\n");
2130       return TRUE;
2131     }
2132   
2133   retval = FALSE;
2134   
2135   message = pop_message_waiting_for_memory (connection);
2136   if (message == NULL)
2137     {
2138       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
2139                   "ActivateService", serial, connection);
2140       goto out;
2141     }
2142
2143   verbose_message_received (connection, message);
2144
2145   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2146     {
2147       if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
2148         {
2149           _dbus_warn ("Message has wrong sender %s\n",
2150                       dbus_message_get_sender (message) ?
2151                       dbus_message_get_sender (message) : "(none)");
2152           goto out;
2153         }
2154       
2155       if (dbus_message_is_error (message,
2156                                  DBUS_ERROR_NO_MEMORY))
2157         {
2158           ; /* good, this is a valid response */
2159         }
2160       else if (dbus_message_is_error (message,
2161                                       DBUS_ERROR_SPAWN_CHILD_SIGNALED))
2162         {
2163           ; /* good, this is expected also */
2164         }
2165       else
2166         {
2167           warn_unexpected (connection, message, "not this error");
2168
2169           goto out;
2170         }
2171     }
2172   else
2173     {
2174       _dbus_warn ("Did not expect to successfully activate segfault service\n");
2175       goto out;
2176     }
2177
2178   retval = TRUE;
2179   
2180  out:
2181   if (message)
2182     dbus_message_unref (message);
2183   
2184   return retval;
2185 }
2186
2187
2188 /* returns TRUE if the correct thing happens,
2189  * but the correct thing may include OOM errors.
2190  */
2191 static dbus_bool_t
2192 check_segfault_service_auto_activation (BusContext     *context,
2193                                         DBusConnection *connection)
2194 {
2195   DBusMessage *message;
2196   dbus_uint32_t serial;
2197   dbus_bool_t retval;
2198   DBusError error;
2199
2200   dbus_error_init (&error);
2201
2202   dbus_error_init (&error);
2203
2204   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteSegfaultService",
2205                                           "/org/freedesktop/TestSuite",
2206                                           "org.freedesktop.TestSuite",
2207                                           "Echo");
2208   
2209   if (message == NULL)
2210     return TRUE;
2211
2212   dbus_message_set_auto_activation (message, TRUE);
2213   
2214   if (!dbus_connection_send (connection, message, &serial))
2215     {
2216       dbus_message_unref (message);
2217       return TRUE;
2218     }
2219
2220   dbus_message_unref (message);
2221   message = NULL;
2222
2223   bus_test_run_everything (context);
2224   block_connection_until_message_from_bus (context, connection);
2225   bus_test_run_everything (context);
2226
2227   if (!dbus_connection_get_is_connected (connection))
2228     {
2229       _dbus_verbose ("connection was disconnected\n");
2230       return TRUE;
2231     }
2232   
2233   retval = FALSE;
2234   
2235   message = pop_message_waiting_for_memory (connection);
2236   if (message == NULL)
2237     {
2238       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
2239                   "Echo message (auto activation)", serial, connection);
2240       goto out;
2241     }
2242
2243   verbose_message_received (connection, message);
2244
2245   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2246     {
2247       if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
2248         {
2249           _dbus_warn ("Message has wrong sender %s\n",
2250                       dbus_message_get_sender (message) ?
2251                       dbus_message_get_sender (message) : "(none)");
2252           goto out;
2253         }
2254       
2255       if (dbus_message_is_error (message,
2256                                  DBUS_ERROR_NO_MEMORY))
2257         {
2258           ; /* good, this is a valid response */
2259         }
2260       else if (dbus_message_is_error (message,
2261                                       DBUS_ERROR_SPAWN_CHILD_SIGNALED))
2262         {
2263           ; /* good, this is expected also */
2264         }
2265       else
2266         {
2267           warn_unexpected (connection, message, "not this error");
2268
2269           goto out;
2270         }
2271     }
2272   else
2273     {
2274       _dbus_warn ("Did not expect to successfully activate segfault service\n");
2275       goto out;
2276     }
2277
2278   retval = TRUE;
2279   
2280  out:
2281   if (message)
2282     dbus_message_unref (message);
2283   
2284   return retval;
2285 }
2286
2287 #define TEST_ECHO_MESSAGE "Test echo message"
2288
2289 /* returns TRUE if the correct thing happens,
2290  * but the correct thing may include OOM errors.
2291  */
2292 static dbus_bool_t
2293 check_existent_service_auto_activation (BusContext     *context,
2294                                         DBusConnection *connection)
2295 {
2296   DBusMessage *message;
2297   dbus_uint32_t serial;
2298   dbus_bool_t retval;
2299   DBusError error;
2300   char *base_service;
2301
2302   base_service = NULL;
2303
2304   dbus_error_init (&error);
2305
2306   message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
2307                                           "/org/freedesktop/TestSuite",
2308                                           "org.freedesktop.TestSuite",
2309                                           "Echo");
2310   
2311   if (message == NULL)
2312     return TRUE;
2313
2314   dbus_message_set_auto_activation (message, TRUE);
2315
2316   if (!dbus_message_append_args (message,
2317                                  DBUS_TYPE_STRING, TEST_ECHO_MESSAGE,
2318                                  DBUS_TYPE_INVALID))
2319     {
2320       dbus_message_unref (message);
2321       return TRUE;
2322     }
2323
2324   if (!dbus_connection_send (connection, message, &serial))
2325     {
2326       dbus_message_unref (message);
2327       return TRUE;
2328     }
2329
2330   dbus_message_unref (message);
2331   message = NULL;
2332
2333   bus_test_run_everything (context);
2334
2335   /* now wait for the message bus to hear back from the activated
2336    * service.
2337    */
2338   block_connection_until_message_from_bus (context, connection);
2339   bus_test_run_everything (context);
2340
2341   if (!dbus_connection_get_is_connected (connection))
2342     {
2343       _dbus_verbose ("connection was disconnected\n");
2344       return TRUE;
2345     }
2346
2347   retval = FALSE;
2348   
2349   /* Should get ServiceCreated for the base service, or an error. */
2350   message = pop_message_waiting_for_memory (connection);
2351   if (message == NULL)
2352     {
2353       _dbus_warn ("Did not receive any messages after auto activation %d on %p\n",
2354                   serial, connection);
2355       goto out;
2356     }
2357
2358   verbose_message_received (connection, message);
2359   _dbus_verbose ("  (after sending %s)\n", "ActivateService");
2360
2361   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2362     {
2363       if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
2364         {
2365           _dbus_warn ("Message has wrong sender %s\n",
2366                       dbus_message_get_sender (message) ?
2367                       dbus_message_get_sender (message) : "(none)");
2368           goto out;
2369         }
2370
2371       if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY) ||
2372           dbus_message_is_error (message, DBUS_ERROR_SPAWN_CHILD_EXITED) ||
2373           dbus_message_is_error (message, DBUS_ERROR_TIMED_OUT))
2374         {
2375           ; /* good, those are expected */
2376           retval = TRUE;
2377           goto out;
2378         }
2379       else
2380         {
2381           _dbus_warn ("Did not expect error %s\n",
2382                       dbus_message_get_error_name (message));
2383           goto out;
2384         }
2385     }
2386   else
2387     {
2388       dbus_bool_t got_service_deleted;
2389       dbus_bool_t got_error;
2390       
2391       if (!check_base_service_activated (context, connection,
2392                                          message, &base_service))
2393         goto out;
2394
2395       dbus_message_unref (message);
2396       message = NULL;
2397
2398       /* We may need to block here for the test service to exit or finish up */
2399       block_connection_until_message_from_bus (context, connection);
2400
2401       /* Should get ServiceCreated for the activated service name,
2402        * ServiceDeleted on the base service name, or an error.
2403        */
2404       message = dbus_connection_borrow_message (connection);
2405       if (message == NULL)
2406         {
2407           _dbus_warn ("Did not receive any messages after base service creation notification\n");
2408           goto out;
2409         }
2410
2411       got_service_deleted = dbus_message_is_signal (message,
2412                                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
2413                                                     "ServiceDeleted");
2414       got_error = dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
2415
2416       dbus_connection_return_message (connection, message);
2417       message = NULL;
2418
2419       if (got_error)
2420         {
2421           if (!check_got_error (context, connection,
2422                                 DBUS_ERROR_SPAWN_CHILD_EXITED,
2423                                 DBUS_ERROR_NO_MEMORY,
2424                                 NULL))
2425             goto out;
2426
2427           /* A service deleted should be coming along now after this error.
2428            * We can also get the error *after* the service deleted.
2429            */
2430           got_service_deleted = TRUE;
2431         }
2432       
2433       if (got_service_deleted)
2434         {
2435           /* The service started up and got a base address, but then
2436            * failed to register under EXISTENT_SERVICE_NAME
2437            */
2438           CheckServiceDeletedData csdd;
2439           
2440           csdd.expected_service_name = base_service;
2441           csdd.failed = FALSE;
2442           bus_test_clients_foreach (check_service_deleted_foreach,
2443                                     &csdd);
2444
2445           if (csdd.failed)
2446             goto out;
2447           
2448           /* Now we should get an error about the service exiting
2449            * if we didn't get it before.
2450            */
2451           if (!got_error)
2452             {
2453               block_connection_until_message_from_bus (context, connection);
2454               
2455               /* and process everything again */
2456               bus_test_run_everything (context);
2457
2458               if (!check_got_error (context, connection,
2459                                     DBUS_ERROR_SPAWN_CHILD_EXITED,
2460                                     NULL))
2461                 goto out;
2462             }
2463         }
2464       else
2465         {
2466           message = pop_message_waiting_for_memory (connection);
2467           if (message == NULL)
2468             {
2469               _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
2470               goto out;
2471             }
2472
2473           /* Check that ServiceCreated was correctly received */
2474           if (!check_service_auto_activated (context, connection, EXISTENT_SERVICE_NAME,
2475                                              base_service, message))
2476             goto out;
2477
2478           dbus_message_unref (message);
2479           message = NULL;
2480         }
2481
2482       /* Note: if this test is run in OOM mode, it will block when the bus
2483        * doesn't send a reply due to OOM.
2484        */
2485       block_connection_until_message_from_bus (context, connection);
2486       
2487       message = pop_message_waiting_for_memory (connection);
2488       if (message == NULL)
2489         {
2490           _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
2491           goto out;
2492         }
2493
2494       if (dbus_message_get_reply_serial (message) != serial)
2495         {
2496           _dbus_warn ("Wrong reply serial\n");
2497           goto out;
2498         }
2499
2500       dbus_message_unref (message);
2501       message = NULL;
2502       
2503       if (!check_send_exit_to_service (context, connection,
2504                                        EXISTENT_SERVICE_NAME,
2505                                        base_service))
2506         goto out;
2507     }
2508   
2509   retval = TRUE;
2510
2511  out:
2512   if (message)
2513     dbus_message_unref (message);
2514
2515   if (base_service)
2516     dbus_free (base_service);
2517
2518   return retval;
2519 }
2520
2521 typedef struct
2522 {
2523   Check1Func func;
2524   BusContext *context;
2525 } Check1Data;
2526
2527 static dbus_bool_t
2528 check_oom_check1_func (void *data)
2529 {
2530   Check1Data *d = data;
2531
2532   if (! (* d->func) (d->context))
2533     return FALSE;
2534   
2535   if (!check_no_leftovers (d->context))
2536     {
2537       _dbus_warn ("Messages were left over, should be covered by test suite\n");
2538       return FALSE;
2539     }
2540
2541   return TRUE;
2542 }
2543
2544 static void
2545 check1_try_iterations (BusContext *context,
2546                        const char *description,
2547                        Check1Func  func)
2548 {
2549   Check1Data d;
2550
2551   d.func = func;
2552   d.context = context;
2553
2554   if (!_dbus_test_oom_handling (description, check_oom_check1_func,
2555                                 &d))
2556     _dbus_assert_not_reached ("test failed");
2557 }
2558
2559 typedef struct
2560 {
2561   Check2Func func;
2562   BusContext *context;
2563   DBusConnection *connection;
2564 } Check2Data;
2565
2566 static dbus_bool_t
2567 check_oom_check2_func (void *data)
2568 {
2569   Check2Data *d = data;
2570
2571   if (! (* d->func) (d->context, d->connection))
2572     return FALSE;
2573   
2574   if (!check_no_leftovers (d->context))
2575     {
2576       _dbus_warn ("Messages were left over, should be covered by test suite");
2577       return FALSE;
2578     }
2579
2580   return TRUE;
2581 }
2582
2583 static void
2584 check2_try_iterations (BusContext     *context,
2585                        DBusConnection *connection,
2586                        const char     *description,
2587                        Check2Func      func)
2588 {
2589   Check2Data d;
2590
2591   d.func = func;
2592   d.context = context;
2593   d.connection = connection;
2594   
2595   if (!_dbus_test_oom_handling (description, check_oom_check2_func,
2596                                 &d))
2597     _dbus_assert_not_reached ("test failed");
2598 }
2599
2600 dbus_bool_t
2601 bus_dispatch_test (const DBusString *test_data_dir)
2602 {
2603   BusContext *context;
2604   DBusConnection *foo;
2605   DBusConnection *bar;
2606   DBusConnection *baz;
2607   DBusError error;
2608
2609   dbus_error_init (&error);
2610   
2611   context = bus_context_new_test (test_data_dir,
2612                                   "valid-config-files/debug-allow-all.conf");
2613   if (context == NULL)
2614     return FALSE;
2615   
2616   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
2617   if (foo == NULL)
2618     _dbus_assert_not_reached ("could not alloc connection");
2619
2620   if (!bus_setup_debug_client (foo))
2621     _dbus_assert_not_reached ("could not set up connection");
2622
2623   if (!check_hello_message (context, foo))
2624     _dbus_assert_not_reached ("hello message failed");
2625
2626   if (!check_add_match_all (context, foo))
2627     _dbus_assert_not_reached ("AddMatch message failed");
2628   
2629   bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
2630   if (bar == NULL)
2631     _dbus_assert_not_reached ("could not alloc connection");
2632
2633   if (!bus_setup_debug_client (bar))
2634     _dbus_assert_not_reached ("could not set up connection");
2635
2636   if (!check_hello_message (context, bar))
2637     _dbus_assert_not_reached ("hello message failed");
2638
2639   if (!check_add_match_all (context, bar))
2640     _dbus_assert_not_reached ("AddMatch message failed");
2641   
2642   baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
2643   if (baz == NULL)
2644     _dbus_assert_not_reached ("could not alloc connection");
2645
2646   if (!bus_setup_debug_client (baz))
2647     _dbus_assert_not_reached ("could not set up connection");
2648
2649   if (!check_hello_message (context, baz))
2650     _dbus_assert_not_reached ("hello message failed");
2651
2652   if (!check_add_match_all (context, baz))
2653     _dbus_assert_not_reached ("AddMatch message failed");
2654   
2655   if (!check_no_leftovers (context))
2656     {
2657       _dbus_warn ("Messages were left over after setting up initial connections");
2658       _dbus_assert_not_reached ("initial connection setup failed");
2659     }
2660   
2661   check1_try_iterations (context, "create_and_hello",
2662                          check_hello_connection);
2663   
2664   check2_try_iterations (context, foo, "nonexistent_service_activation",
2665                          check_nonexistent_service_activation);
2666
2667   check2_try_iterations (context, foo, "segfault_service_activation",
2668                          check_segfault_service_activation);
2669   
2670   check2_try_iterations (context, foo, "existent_service_activation",
2671                          check_existent_service_activation);
2672   
2673   check2_try_iterations (context, foo, "nonexistent_service_auto_activation",
2674                          check_nonexistent_service_auto_activation);
2675   
2676   check2_try_iterations (context, foo, "segfault_service_auto_activation",
2677                          check_segfault_service_auto_activation);
2678
2679 #if 0
2680   /* Note: need to resolve some issues with the testing code in order to run
2681    * this in oom (handle that we sometimes don't get replies back from the bus
2682    * when oom happens, without blocking the test).
2683    */
2684   check2_try_iterations (context, foo, "existent_service_auto_activation",
2685                          check_existent_service_auto_activation);
2686 #endif
2687   
2688   if (!check_existent_service_auto_activation (context, foo))
2689     _dbus_assert_not_reached ("existent service auto activation failed");
2690
2691   _dbus_verbose ("Disconnecting foo, bar, and baz\n");
2692
2693   kill_client_connection_unchecked (foo);
2694   kill_client_connection_unchecked (bar);
2695   kill_client_connection_unchecked (baz);
2696
2697   bus_context_unref (context);
2698   
2699   return TRUE;
2700 }
2701
2702 dbus_bool_t
2703 bus_dispatch_sha1_test (const DBusString *test_data_dir)
2704 {
2705   BusContext *context;
2706   DBusConnection *foo;
2707   DBusError error;
2708
2709   dbus_error_init (&error);
2710   
2711   /* Test SHA1 authentication */
2712   _dbus_verbose ("Testing SHA1 context\n");
2713   
2714   context = bus_context_new_test (test_data_dir,
2715                                   "valid-config-files/debug-allow-all-sha1.conf");
2716   if (context == NULL)
2717     return FALSE;
2718
2719   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
2720   if (foo == NULL)
2721     _dbus_assert_not_reached ("could not alloc connection");
2722
2723   if (!bus_setup_debug_client (foo))
2724     _dbus_assert_not_reached ("could not set up connection");
2725
2726   if (!check_hello_message (context, foo))
2727     _dbus_assert_not_reached ("hello message failed");
2728
2729   if (!check_add_match_all (context, foo))
2730     _dbus_assert_not_reached ("addmatch message failed");
2731   
2732   if (!check_no_leftovers (context))
2733     {
2734       _dbus_warn ("Messages were left over after setting up initial SHA-1 connection\n");
2735       _dbus_assert_not_reached ("initial connection setup failed");
2736     }
2737   
2738   check1_try_iterations (context, "create_and_hello_sha1",
2739                          check_hello_connection);
2740
2741   kill_client_connection_unchecked (foo);
2742
2743   bus_context_unref (context);
2744
2745   return TRUE;
2746 }
2747
2748 #endif /* DBUS_BUILD_TESTS */