2003-04-10 Havoc Pennington <hp@pobox.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  *
7  * Licensed under the Academic Free License version 1.2
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "dispatch.h"
26 #include "connection.h"
27 #include "driver.h"
28 #include "services.h"
29 #include "utils.h"
30 #include "bus.h"
31 #include "test.h"
32 #include <dbus/dbus-internals.h>
33 #include <string.h>
34
35 static int message_handler_slot = -1;
36 static int message_handler_slot_refcount;
37
38 typedef struct
39 {
40   DBusMessage    *message;
41   BusTransaction *transaction;
42   DBusError      *error;
43 } SendMessageData;
44
45 static dbus_bool_t
46 send_one_message (DBusConnection *connection, void *data)
47 {
48   SendMessageData *d = data;
49   
50   if (!bus_connection_is_active (connection))
51     return TRUE;
52
53   if (!bus_transaction_send_message (d->transaction,
54                                      connection,
55                                      d->message))
56     {
57       BUS_SET_OOM (d->error);
58       return FALSE;
59     }
60
61   return TRUE;
62 }
63
64 dbus_bool_t
65 bus_dispatch_broadcast_message (BusTransaction *transaction,
66                                 DBusMessage    *message,
67                                 DBusError      *error)
68 {
69   DBusError tmp_error;
70   SendMessageData d;
71   BusConnections *connections;
72
73   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
74   
75   _dbus_assert (dbus_message_get_sender (message) != NULL);
76
77   connections = bus_transaction_get_connections (transaction);
78   
79   dbus_error_init (&tmp_error);
80   d.message = message;
81   d.transaction = transaction;
82   d.error = &tmp_error;
83   
84   bus_connections_foreach (connections, send_one_message, &d);
85
86   if (dbus_error_is_set (&tmp_error))
87     {
88       dbus_move_error (&tmp_error, error);
89       return FALSE;
90     }
91   else
92     return TRUE;
93 }
94
95 static dbus_bool_t
96 send_service_nonexistent_error (BusTransaction *transaction,
97                                 DBusConnection *connection,
98                                 const char     *service_name,
99                                 DBusMessage    *in_reply_to,
100                                 DBusError      *error)
101 {
102   DBusMessage *error_reply;
103   DBusString error_message;
104   const char *error_str;
105
106   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
107   
108   /* Trying to send a message to a non-existant service,
109    * bounce back an error message.
110    */
111           
112   if (!_dbus_string_init (&error_message))
113     {
114       BUS_SET_OOM (error);
115       return FALSE;
116     }
117
118   if (!_dbus_string_append (&error_message, "Service \"") ||
119       !_dbus_string_append (&error_message, service_name) ||
120       !_dbus_string_append (&error_message, "\" does not exist"))
121     {
122       _dbus_string_free (&error_message);
123       BUS_SET_OOM (error);
124       return FALSE;
125     }
126               
127   error_str = _dbus_string_get_const_data (&error_message);
128   error_reply = dbus_message_new_error_reply (in_reply_to,
129                                               DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
130                                               error_str);
131
132   _dbus_string_free (&error_message);
133               
134   if (error_reply == NULL)
135     {
136       BUS_SET_OOM (error);
137       return FALSE;
138     }
139
140   if (!dbus_message_set_sender (error_reply, DBUS_SERVICE_DBUS))
141     {
142       dbus_message_unref (error_reply);
143       BUS_SET_OOM (error);
144       return FALSE;
145     }      
146   
147   if (!bus_transaction_send_message (transaction, connection, error_reply))
148     {
149       dbus_message_unref (error_reply);
150       BUS_SET_OOM (error);
151       return FALSE;
152     }
153               
154   dbus_message_unref (error_reply);
155
156   return TRUE;
157 }
158
159 static void
160 bus_dispatch (DBusConnection *connection,
161               DBusMessage    *message)
162 {
163   const char *sender, *service_name, *message_name;
164   DBusError error;
165   BusTransaction *transaction;
166   BusContext *context;
167   
168   transaction = NULL;
169   dbus_error_init (&error);
170   
171   context = bus_connection_get_context (connection);
172   _dbus_assert (context != NULL);
173   
174   /* If we can't even allocate an OOM error, we just go to sleep
175    * until we can.
176    */
177   while (!bus_connection_preallocate_oom_error (connection))
178     _dbus_wait_for_memory ();
179   
180   /* Ref connection in case we disconnect it at some point in here */
181   dbus_connection_ref (connection);
182
183   service_name = dbus_message_get_service (message);
184   message_name = dbus_message_get_name (message);
185
186   _dbus_assert (message_name != NULL); /* DBusMessageLoader is supposed to check this */
187
188   _dbus_verbose ("DISPATCH: %s to %s\n",
189                  message_name, service_name ? service_name : "peer");
190   
191   /* If service_name is NULL, this is a message to the bus daemon, not intended
192    * to actually go "on the bus"; e.g. a peer-to-peer ping. Handle these
193    * immediately, especially disconnection messages.
194    */
195   if (service_name == NULL)
196     {      
197       if (strcmp (message_name, DBUS_MESSAGE_LOCAL_DISCONNECT) == 0)
198         bus_connection_disconnected (connection);
199
200       /* DBusConnection also handles some of these automatically, we leave
201        * it to do so.
202        */
203       goto out;
204     }
205
206   _dbus_assert (service_name != NULL); /* this message is intended for bus routing */
207   
208   /* Create our transaction */
209   transaction = bus_transaction_new (context);
210   if (transaction == NULL)
211     {
212       BUS_SET_OOM (&error);
213       goto out;
214     }
215   
216   /* Assign a sender to the message */
217   if (bus_connection_is_active (connection))
218     {
219       sender = bus_connection_get_name (connection);
220       _dbus_assert (sender != NULL);
221
222       if (!dbus_message_set_sender (message, sender))
223         {
224           BUS_SET_OOM (&error);
225           goto out;
226         }
227
228       /* We need to refetch the service name here, because
229        * dbus_message_set_sender can cause the header to be
230        * reallocated, and thus the service_name pointer will become
231        * invalid.
232        */
233       service_name = dbus_message_get_service (message);
234     }
235
236   if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
237     {
238       if (!bus_driver_handle_message (connection, transaction, message, &error))
239         goto out;
240     }
241   else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
242     {
243       _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
244       dbus_connection_disconnect (connection);
245     }
246   /* FIXME what if we un-special-case this service and just have a flag
247    * on services that all service owners will get messages to it, not just
248    * the primary owner.
249    */
250   else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0) /* spam! */
251     {
252       if (!bus_dispatch_broadcast_message (transaction, message, &error))
253         goto out;
254     }
255   else  /* route to named service */
256     {
257       DBusString service_string;
258       BusService *service;
259       BusRegistry *registry;
260
261       registry = bus_connection_get_registry (connection);
262       
263       _dbus_string_init_const (&service_string, service_name);
264       service = bus_registry_lookup (registry, &service_string);
265
266       if (service == NULL)
267         {
268           if (!send_service_nonexistent_error (transaction, connection,
269                                                service_name,
270                                                message, &error))
271             goto out;
272         }
273       else
274         {
275           _dbus_assert (bus_service_get_primary_owner (service) != NULL);
276       
277           /* Dispatch the message */
278           if (!bus_transaction_send_message (transaction,
279                                              bus_service_get_primary_owner (service),
280                                              message))
281             {
282               BUS_SET_OOM (&error);
283               goto out;
284             }
285         }
286     }
287   
288  out:
289   if (dbus_error_is_set (&error))
290     {
291       if (!dbus_connection_get_is_connected (connection))
292         {
293           /* If we disconnected it, we won't bother to send it any error
294            * messages.
295            */
296         }
297       else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
298         {
299           bus_connection_send_oom_error (connection, message);
300
301           /* cancel transaction due to OOM */
302           if (transaction != NULL)
303             {
304               bus_transaction_cancel_and_free (transaction);
305               transaction = NULL;
306             }
307         }
308       else
309         {
310           /* Try to send the real error, if no mem to do that, send
311            * the OOM error
312            */
313           _dbus_assert (transaction != NULL);
314           
315           if (!bus_transaction_send_error_reply (transaction, connection,
316                                                  &error, message))
317             {
318               bus_connection_send_oom_error (connection, message);
319
320               /* cancel transaction due to OOM */
321               if (transaction != NULL)
322                 {
323                   bus_transaction_cancel_and_free (transaction);
324                   transaction = NULL;
325                 }
326             }
327         }
328       
329       dbus_error_free (&error);
330     }
331
332   if (transaction != NULL)
333     {
334       bus_transaction_execute_and_free (transaction);
335     }
336
337   dbus_connection_unref (connection);
338 }
339
340 static DBusHandlerResult
341 bus_dispatch_message_handler (DBusMessageHandler *handler,
342                               DBusConnection     *connection,
343                               DBusMessage        *message,
344                               void               *user_data)
345 {
346   bus_dispatch (connection, message);
347   
348   return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
349 }
350
351 static dbus_bool_t
352 message_handler_slot_ref (void)
353 {
354   if (message_handler_slot < 0)
355     {
356       message_handler_slot = dbus_connection_allocate_data_slot ();
357       
358       if (message_handler_slot < 0)
359         return FALSE;
360
361       _dbus_assert (message_handler_slot_refcount == 0);
362     }  
363
364   message_handler_slot_refcount += 1;
365
366   return TRUE;
367 }
368
369 static void
370 message_handler_slot_unref (void)
371 {
372   _dbus_assert (message_handler_slot_refcount > 0);
373
374   message_handler_slot_refcount -= 1;
375   
376   if (message_handler_slot_refcount == 0)
377     {
378       dbus_connection_free_data_slot (message_handler_slot);
379       message_handler_slot = -1;
380     }
381 }
382
383 static void
384 free_message_handler (void *data)
385 {
386   DBusMessageHandler *handler = data;
387   
388   _dbus_assert (message_handler_slot >= 0);
389   _dbus_assert (message_handler_slot_refcount > 0);
390   
391   dbus_message_handler_unref (handler);
392   message_handler_slot_unref ();
393 }
394
395 dbus_bool_t
396 bus_dispatch_add_connection (DBusConnection *connection)
397 {
398   DBusMessageHandler *handler;
399
400   if (!message_handler_slot_ref ())
401     return FALSE;
402   
403   handler = dbus_message_handler_new (bus_dispatch_message_handler, NULL, NULL);  
404   if (handler == NULL)
405     {
406       message_handler_slot_unref ();
407       return FALSE;
408     }    
409   
410   if (!dbus_connection_add_filter (connection, handler))
411     {
412       dbus_message_handler_unref (handler);
413       message_handler_slot_unref ();
414       
415       return FALSE;
416     }
417
418   _dbus_assert (message_handler_slot >= 0);
419   _dbus_assert (message_handler_slot_refcount > 0);
420   
421   if (!dbus_connection_set_data (connection,
422                                  message_handler_slot,
423                                  handler,
424                                  free_message_handler))
425     {
426       dbus_message_handler_unref (handler);
427       message_handler_slot_unref ();
428
429       return FALSE;
430     }
431
432   return TRUE;
433 }
434
435 void
436 bus_dispatch_remove_connection (DBusConnection *connection)
437 {
438   /* Here we tell the bus driver that we want to get off. */
439   bus_driver_remove_connection (connection);
440
441   dbus_connection_set_data (connection,
442                             message_handler_slot,
443                             NULL, NULL);
444 }
445
446 #ifdef DBUS_BUILD_TESTS
447
448 typedef dbus_bool_t (* Check1Func) (BusContext     *context);
449 typedef dbus_bool_t (* Check2Func) (BusContext     *context,
450                                     DBusConnection *connection);
451
452 static dbus_bool_t check_no_leftovers (BusContext *context);
453
454 static void
455 block_connection_until_message_from_bus (BusContext     *context,
456                                          DBusConnection *connection)
457 {
458   while (dbus_connection_get_dispatch_status (connection) ==
459          DBUS_DISPATCH_COMPLETE &&
460          dbus_connection_get_is_connected (connection))
461     {
462       bus_test_run_bus_loop (context, TRUE);
463       bus_test_run_clients_loop (FALSE);
464     }
465 }
466
467 /* compensate for fact that pop_message() can return #NULL due to OOM */
468 static DBusMessage*
469 pop_message_waiting_for_memory (DBusConnection *connection)
470 {
471   while (dbus_connection_get_dispatch_status (connection) ==
472          DBUS_DISPATCH_NEED_MEMORY)
473     _dbus_wait_for_memory ();
474
475   return dbus_connection_pop_message (connection);
476 }
477
478 typedef struct
479 {
480   const char *expected_service_name;
481   dbus_bool_t failed;
482 } CheckServiceDeletedData;
483
484 static dbus_bool_t
485 check_service_deleted_foreach (DBusConnection *connection,
486                                void           *data)
487 {
488   CheckServiceDeletedData *d = data;
489   DBusMessage *message;
490   DBusError error;
491   char *service_name;
492
493   dbus_error_init (&error);
494   d->failed = TRUE;
495   service_name = NULL;
496   
497   message = pop_message_waiting_for_memory (connection);
498   if (message == NULL)
499     {
500       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
501                   connection, DBUS_MESSAGE_SERVICE_DELETED);
502       goto out;
503     }
504   else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_DELETED))
505     {
506       _dbus_warn ("Received message %s on %p, expecting %s\n",
507                   dbus_message_get_name (message),
508                   connection, DBUS_MESSAGE_SERVICE_DELETED);
509       goto out;
510     }
511   else
512     {
513       if (!dbus_message_get_args (message, &error,
514                                   DBUS_TYPE_STRING, &service_name,
515                                   DBUS_TYPE_INVALID))
516         {
517           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
518             {
519               _dbus_verbose ("no memory to get service name arg\n");
520             }
521           else
522             {
523               _dbus_assert (dbus_error_is_set (&error));
524               _dbus_warn ("Did not get the expected single string argument\n");
525               goto out;
526             }
527         }
528       else if (strcmp (service_name, d->expected_service_name) != 0)
529         {
530           _dbus_warn ("expected deletion of service %s, got deletion of %s\n",
531                       d->expected_service_name,
532                       service_name);
533           goto out;
534         }
535     }
536
537   d->failed = FALSE;
538   
539  out:
540   dbus_free (service_name);
541   dbus_error_free (&error);
542   
543   if (message)
544     dbus_message_unref (message);
545
546   return !d->failed;
547 }
548
549 static void
550 kill_client_connection (BusContext     *context,
551                         DBusConnection *connection)
552 {
553   char *base_service;
554   const char *s;
555   CheckServiceDeletedData csdd;
556
557   _dbus_verbose ("killing connection %p\n", connection);
558   
559   s = dbus_bus_get_base_service (connection);
560   _dbus_assert (s != NULL);
561
562   while ((base_service = _dbus_strdup (s)) == NULL)
563     _dbus_wait_for_memory ();
564
565   dbus_connection_ref (connection);
566   
567   /* kick in the disconnect handler that unrefs the connection */
568   dbus_connection_disconnect (connection);
569
570   bus_test_run_everything (context);
571   
572   _dbus_assert (bus_test_client_listed (connection));
573   
574   /* Run disconnect handler in test.c */
575   if (bus_connection_dispatch_one_message (connection))
576     _dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
577   
578   _dbus_assert (!dbus_connection_get_is_connected (connection));
579   dbus_connection_unref (connection);
580   connection = NULL;
581   _dbus_assert (!bus_test_client_listed (connection));
582   
583   csdd.expected_service_name = base_service;
584   csdd.failed = FALSE;
585
586   bus_test_clients_foreach (check_service_deleted_foreach,
587                             &csdd);
588
589   dbus_free (base_service);
590   
591   if (csdd.failed)
592     _dbus_assert_not_reached ("didn't get the expected ServiceDeleted messages");
593   
594   if (!check_no_leftovers (context))
595     _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
596 }
597
598 static void
599 kill_client_connection_unchecked (DBusConnection *connection)
600 {
601   /* This kills the connection without expecting it to affect
602    * the rest of the bus.
603    */  
604   _dbus_verbose ("Unchecked kill of connection %p\n", connection);
605
606   dbus_connection_ref (connection);
607   dbus_connection_disconnect (connection);
608   /* dispatching disconnect handler will unref once */
609   if (bus_connection_dispatch_one_message (connection))
610     _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
611   dbus_connection_unref (connection);
612   _dbus_assert (!bus_test_client_listed (connection));
613 }
614
615 typedef struct
616 {
617   dbus_bool_t failed;
618 } CheckNoMessagesData;
619
620 static dbus_bool_t
621 check_no_messages_foreach (DBusConnection *connection,
622                            void           *data)
623 {
624   CheckNoMessagesData *d = data;
625   DBusMessage *message;
626
627   message = pop_message_waiting_for_memory (connection);
628   if (message != NULL)
629     {
630       _dbus_warn ("Received message %s on %p, expecting no messages\n",
631                   dbus_message_get_name (message), connection);
632       d->failed = TRUE;
633     }
634
635   if (message)
636     dbus_message_unref (message);
637   return !d->failed;
638 }
639
640 typedef struct
641 {
642   DBusConnection *skip_connection;
643   const char *expected_service_name;
644   dbus_bool_t failed;
645 } CheckServiceCreatedData;
646
647 static dbus_bool_t
648 check_service_created_foreach (DBusConnection *connection,
649                                void           *data)
650 {
651   CheckServiceCreatedData *d = data;
652   DBusMessage *message;
653   DBusError error;
654   char *service_name;
655
656   if (connection == d->skip_connection)
657     return TRUE;
658
659   dbus_error_init (&error);
660   d->failed = TRUE;
661   service_name = NULL;
662   
663   message = pop_message_waiting_for_memory (connection);
664   if (message == NULL)
665     {
666       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
667                   connection, DBUS_MESSAGE_SERVICE_CREATED);
668       goto out;
669     }
670   else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
671     {
672       _dbus_warn ("Received message %s on %p, expecting %s\n",
673                   dbus_message_get_name (message),
674                   connection, DBUS_MESSAGE_SERVICE_CREATED);
675       goto out;
676     }
677   else
678     {
679       if (!dbus_message_get_args (message, &error,
680                                   DBUS_TYPE_STRING, &service_name,
681                                   DBUS_TYPE_INVALID))
682         {
683           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
684             {
685               _dbus_verbose ("no memory to get service name arg\n");
686             }
687           else
688             {
689               _dbus_assert (dbus_error_is_set (&error));
690               _dbus_warn ("Did not get the expected single string argument\n");
691               goto out;
692             }
693         }
694       else if (strcmp (service_name, d->expected_service_name) != 0)
695         {
696           _dbus_warn ("expected creation of service %s, got creation of %s\n",
697                       d->expected_service_name,
698                       service_name);
699           goto out;
700         }
701     }
702
703   d->failed = FALSE;
704   
705  out:
706   dbus_free (service_name);
707   dbus_error_free (&error);
708   
709   if (message)
710     dbus_message_unref (message);
711
712   return !d->failed;
713 }
714
715 static dbus_bool_t
716 check_no_leftovers (BusContext *context)
717 {
718   CheckNoMessagesData nmd;
719
720   nmd.failed = FALSE;
721   bus_test_clients_foreach (check_no_messages_foreach,
722                             &nmd);
723   
724   if (nmd.failed)
725     return FALSE;
726   else
727     return TRUE;
728 }
729
730 /* returns TRUE if the correct thing happens,
731  * but the correct thing may include OOM errors.
732  */
733 static dbus_bool_t
734 check_hello_message (BusContext     *context,
735                      DBusConnection *connection)
736 {
737   DBusMessage *message;
738   dbus_int32_t serial;
739   dbus_bool_t retval;
740   DBusError error;
741   char *name;
742   char *acquired;
743   
744   dbus_error_init (&error);
745   name = NULL;
746   acquired = NULL;
747   
748   message = dbus_message_new (DBUS_SERVICE_DBUS,
749                               DBUS_MESSAGE_HELLO);
750
751   if (message == NULL)
752     return TRUE;
753
754   if (!dbus_connection_send (connection, message, &serial))
755     {
756       dbus_message_unref (message);
757       return TRUE;
758     }
759
760   dbus_message_unref (message);
761   message = NULL;
762
763   bus_test_run_everything (context);
764
765   if (!dbus_connection_get_is_connected (connection))
766     {
767       _dbus_verbose ("connection was disconnected\n");
768       return TRUE;
769     }
770   
771   retval = FALSE;
772   
773   message = pop_message_waiting_for_memory (connection);
774   if (message == NULL)
775     {
776       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
777                   DBUS_MESSAGE_HELLO, serial, connection);
778       goto out;
779     }
780
781   _dbus_verbose ("Received %s on %p\n",
782                  dbus_message_get_name (message), connection);
783
784   if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
785     {
786       _dbus_warn ("Message has wrong sender %s\n",
787                   dbus_message_get_sender (message) ?
788                   dbus_message_get_sender (message) : "(none)");
789       goto out;
790     }
791   
792   if (dbus_message_get_is_error (message))
793     {
794       if (dbus_message_name_is (message,
795                                 DBUS_ERROR_NO_MEMORY))
796         {
797           ; /* good, this is a valid response */
798         }
799       else
800         {
801           _dbus_warn ("Did not expect error %s\n",
802                       dbus_message_get_name (message));
803           goto out;
804         }
805     }
806   else
807     {
808       CheckServiceCreatedData scd;
809       
810       if (dbus_message_name_is (message,
811                                 DBUS_MESSAGE_HELLO))
812         {
813           ; /* good, expected */
814         }
815       else
816         {
817           _dbus_warn ("Did not expect reply %s\n",
818                       dbus_message_get_name (message));
819           goto out;
820         }
821
822     retry_get_hello_name:
823       if (!dbus_message_get_args (message, &error,
824                                   DBUS_TYPE_STRING, &name,
825                                   DBUS_TYPE_INVALID))
826         {
827           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
828             {
829               _dbus_verbose ("no memory to get service name arg from hello\n");
830               dbus_error_free (&error);
831               _dbus_wait_for_memory ();
832               goto retry_get_hello_name;
833             }
834           else
835             {
836               _dbus_assert (dbus_error_is_set (&error));
837               _dbus_warn ("Did not get the expected single string argument to hello\n");
838               goto out;
839             }
840         }
841
842       _dbus_verbose ("Got hello name: %s\n", name);
843
844       while (!dbus_bus_set_base_service (connection, name))
845         _dbus_wait_for_memory ();
846       
847       scd.skip_connection = NULL;
848       scd.failed = FALSE;
849       scd.expected_service_name = name;
850       bus_test_clients_foreach (check_service_created_foreach,
851                                 &scd);
852       
853       if (scd.failed)
854         goto out;
855       
856       /* Client should also have gotten ServiceAcquired */
857       dbus_message_unref (message);
858       message = pop_message_waiting_for_memory (connection);
859       if (message == NULL)
860         {
861           _dbus_warn ("Expecting %s, got nothing\n",
862                       DBUS_MESSAGE_SERVICE_ACQUIRED);
863           goto out;
864         }
865       
866     retry_get_acquired_name:
867       if (!dbus_message_get_args (message, &error,
868                                   DBUS_TYPE_STRING, &acquired,
869                                   DBUS_TYPE_INVALID))
870         {
871           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
872             {
873               _dbus_verbose ("no memory to get service name arg from acquired\n");
874               dbus_error_free (&error);
875               _dbus_wait_for_memory ();
876               goto retry_get_acquired_name;
877             }
878           else
879             {
880               _dbus_assert (dbus_error_is_set (&error));
881               _dbus_warn ("Did not get the expected single string argument to ServiceAcquired\n");
882               goto out;
883             }
884         }
885
886       _dbus_verbose ("Got acquired name: %s\n", acquired);
887
888       if (strcmp (acquired, name) != 0)
889         {
890           _dbus_warn ("Acquired name is %s but expected %s\n",
891                       acquired, name);
892           goto out;
893         }
894     }
895
896   if (!check_no_leftovers (context))
897     goto out;
898   
899   retval = TRUE;
900   
901  out:
902   dbus_error_free (&error);
903   
904   dbus_free (name);
905   dbus_free (acquired);
906   
907   if (message)
908     dbus_message_unref (message);
909   
910   return retval;
911 }
912
913 /* returns TRUE if the correct thing happens,
914  * but the correct thing may include OOM errors.
915  */
916 static dbus_bool_t
917 check_hello_connection (BusContext *context)
918 {
919   DBusConnection *connection;
920   DBusError error;
921
922   dbus_error_init (&error);
923
924   connection = dbus_connection_open ("debug-pipe:name=test-server", &error);
925   if (connection == NULL)
926     {
927       _DBUS_ASSERT_ERROR_IS_SET (&error);
928       dbus_error_free (&error);
929       return TRUE;
930     }
931
932   if (!bus_setup_debug_client (connection))
933     {
934       dbus_connection_disconnect (connection);
935       dbus_connection_unref (connection);
936       return TRUE;
937     }
938
939   if (!check_hello_message (context, connection))
940     return FALSE;
941
942   if (dbus_bus_get_base_service (connection) == NULL)
943     {
944       /* We didn't successfully register, so we can't
945        * do the usual kill_client_connection() checks
946        */
947       kill_client_connection_unchecked (connection);
948     }
949   else
950     {
951       kill_client_connection (context, connection);
952     }
953
954   return TRUE;
955 }
956
957 #define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
958
959 /* returns TRUE if the correct thing happens,
960  * but the correct thing may include OOM errors.
961  */
962 static dbus_bool_t
963 check_nonexistent_service_activation (BusContext     *context,
964                                       DBusConnection *connection)
965 {
966   DBusMessage *message;
967   dbus_int32_t serial;
968   dbus_bool_t retval;
969   DBusError error;
970   
971   dbus_error_init (&error);
972   
973   message = dbus_message_new (DBUS_SERVICE_DBUS,
974                               DBUS_MESSAGE_ACTIVATE_SERVICE);
975
976   if (message == NULL)
977     return TRUE;
978
979   if (!dbus_message_append_args (message,
980                                  DBUS_TYPE_STRING, NONEXISTENT_SERVICE_NAME,
981                                  DBUS_TYPE_UINT32, 0,
982                                  DBUS_TYPE_INVALID))
983     {
984       dbus_message_unref (message);
985       return TRUE;
986     }
987   
988   if (!dbus_connection_send (connection, message, &serial))
989     {
990       dbus_message_unref (message);
991       return TRUE;
992     }
993
994   dbus_message_unref (message);
995   message = NULL;
996
997   bus_test_run_everything (context);
998   block_connection_until_message_from_bus (context, connection);
999   bus_test_run_everything (context);
1000
1001   if (!dbus_connection_get_is_connected (connection))
1002     {
1003       _dbus_verbose ("connection was disconnected\n");
1004       return TRUE;
1005     }
1006   
1007   retval = FALSE;
1008   
1009   message = pop_message_waiting_for_memory (connection);
1010   if (message == NULL)
1011     {
1012       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1013                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
1014       goto out;
1015     }
1016
1017   _dbus_verbose ("Received %s on %p\n",
1018                  dbus_message_get_name (message), connection);
1019
1020   if (dbus_message_get_is_error (message))
1021     {
1022       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
1023         {
1024           _dbus_warn ("Message has wrong sender %s\n",
1025                       dbus_message_get_sender (message) ?
1026                       dbus_message_get_sender (message) : "(none)");
1027           goto out;
1028         }
1029       
1030       if (dbus_message_name_is (message,
1031                                 DBUS_ERROR_NO_MEMORY))
1032         {
1033           ; /* good, this is a valid response */
1034         }
1035       else if (dbus_message_name_is (message,
1036                                      DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1037         {
1038           ; /* good, this is expected also */
1039         }
1040       else
1041         {
1042           _dbus_warn ("Did not expect error %s\n",
1043                       dbus_message_get_name (message));
1044           goto out;
1045         }
1046     }
1047   else
1048     {
1049       _dbus_warn ("Did not expect to successfully activate %s\n",
1050                   NONEXISTENT_SERVICE_NAME);
1051       goto out;
1052     }
1053
1054   retval = TRUE;
1055   
1056  out:
1057   if (message)
1058     dbus_message_unref (message);
1059   
1060   return retval;
1061 }
1062
1063 static dbus_bool_t
1064 check_base_service_activated (BusContext     *context,
1065                               DBusConnection *connection,
1066                               DBusMessage    *initial_message,
1067                               char          **base_service_p)
1068 {
1069   DBusMessage *message;
1070   dbus_bool_t retval;
1071   DBusError error;
1072   char *base_service;
1073   
1074   base_service = NULL;
1075   retval = FALSE;
1076   
1077   dbus_error_init (&error);
1078
1079   message = initial_message;
1080   dbus_message_ref (message);  
1081
1082   if (dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
1083     {
1084       char *service_name;
1085       CheckServiceCreatedData scd;
1086
1087     reget_service_name_arg:
1088       if (!dbus_message_get_args (message, &error,
1089                                   DBUS_TYPE_STRING, &service_name,
1090                                   DBUS_TYPE_INVALID))
1091         {
1092           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1093             {
1094               dbus_error_free (&error);
1095               _dbus_wait_for_memory ();
1096               goto reget_service_name_arg;
1097             }
1098           else
1099             {
1100               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1101                           dbus_message_get_name (message),
1102                           error.message);
1103               dbus_error_free (&error);
1104               goto out;
1105             }
1106         }
1107
1108       if (*service_name != ':')
1109         {
1110           _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
1111                       service_name);
1112           goto out;
1113         }
1114               
1115       base_service = service_name;
1116       service_name = NULL;
1117       
1118       scd.skip_connection = connection;
1119       scd.failed = FALSE;
1120       scd.expected_service_name = base_service;
1121       bus_test_clients_foreach (check_service_created_foreach,
1122                                 &scd);
1123       
1124       if (scd.failed)
1125         goto out;
1126     }
1127   else
1128     {
1129       _dbus_warn ("Expected to get base service ServiceCreated, instead got %s\n",
1130                   dbus_message_get_name (message));
1131       goto out;
1132     }
1133
1134   retval = TRUE;
1135
1136   if (base_service_p)
1137     {
1138       *base_service_p = base_service;
1139       base_service = NULL;
1140     }
1141   
1142  out:
1143   if (message)
1144     dbus_message_unref (message);
1145
1146   if (base_service)
1147     dbus_free (base_service);
1148   
1149   return retval;
1150 }
1151
1152 static dbus_bool_t
1153 check_service_activated (BusContext     *context,
1154                          DBusConnection *connection,
1155                          const char     *activated_name,
1156                          const char     *base_service_name,
1157                          DBusMessage    *initial_message)
1158 {
1159   DBusMessage *message;
1160   dbus_bool_t retval;
1161   DBusError error;
1162   dbus_uint32_t activation_result;
1163   
1164   retval = FALSE;
1165   
1166   dbus_error_init (&error);
1167
1168   message = initial_message;
1169   dbus_message_ref (message);
1170
1171   if (dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
1172     {
1173       char *service_name;
1174       CheckServiceCreatedData scd;
1175
1176     reget_service_name_arg:
1177       if (!dbus_message_get_args (message, &error,
1178                                   DBUS_TYPE_STRING, &service_name,
1179                                   DBUS_TYPE_INVALID))
1180         {
1181           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1182             {
1183               dbus_error_free (&error);
1184               _dbus_wait_for_memory ();
1185               goto reget_service_name_arg;
1186             }
1187           else
1188             {
1189               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1190                           dbus_message_get_name (message),
1191                           error.message);
1192               dbus_error_free (&error);
1193               goto out;
1194             }
1195         }
1196
1197       if (strcmp (service_name, activated_name) != 0)
1198         {
1199           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
1200                       activated_name, service_name);
1201           dbus_free (service_name);
1202           goto out;
1203         }
1204       
1205       scd.skip_connection = connection;
1206       scd.failed = FALSE;
1207       scd.expected_service_name = service_name;
1208       bus_test_clients_foreach (check_service_created_foreach,
1209                                 &scd);
1210           
1211       dbus_free (service_name);
1212
1213       if (scd.failed)
1214         goto out;
1215           
1216       dbus_message_unref (message);
1217       message = pop_message_waiting_for_memory (connection);
1218       if (message == NULL)
1219         {
1220           _dbus_warn ("Expected a reply to %s, got nothing\n",
1221                       DBUS_MESSAGE_ACTIVATE_SERVICE);
1222           goto out;
1223         }
1224     }
1225   else
1226     {
1227       _dbus_warn ("Expected to get service %s ServiceCreated, instead got %s\n",
1228                   activated_name, dbus_message_get_name (message));
1229       goto out;
1230     }
1231   
1232   if (!dbus_message_name_is (message, DBUS_MESSAGE_ACTIVATE_SERVICE))
1233     {
1234       _dbus_warn ("Expected reply to %s, got message %s instead\n",
1235                   DBUS_MESSAGE_ACTIVATE_SERVICE,
1236                   dbus_message_get_name (message));
1237       goto out;
1238     }
1239
1240   activation_result = 0;
1241   if (!dbus_message_get_args (message, &error,
1242                               DBUS_TYPE_UINT32, &activation_result,
1243                               DBUS_TYPE_INVALID))
1244     {
1245       if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1246         {
1247           _dbus_warn ("Did not have activation result first argument to %s: %s\n",
1248                       DBUS_MESSAGE_ACTIVATE_SERVICE, error.message);
1249           dbus_error_free (&error);
1250           goto out;
1251         }
1252
1253       dbus_error_free (&error);
1254     }
1255   else
1256     {
1257       if (activation_result == DBUS_ACTIVATION_REPLY_ACTIVATED)
1258         ; /* Good */
1259       else if (activation_result == DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE)
1260         ; /* Good also */
1261       else
1262         {
1263           _dbus_warn ("Activation result was 0x%x, no good.\n",
1264                       activation_result);
1265           goto out;
1266         }
1267     }
1268
1269   dbus_message_unref (message);
1270   message = NULL;
1271       
1272   if (!check_no_leftovers (context))
1273     {
1274       _dbus_warn ("Messages were left over after verifying existent activation results\n");
1275       goto out;
1276     }
1277
1278   retval = TRUE;
1279   
1280  out:
1281   if (message)
1282     dbus_message_unref (message);
1283   
1284   return retval;
1285 }
1286
1287 static dbus_bool_t
1288 check_service_deactivated (BusContext     *context,
1289                            DBusConnection *connection,
1290                            const char     *activated_name,
1291                            const char     *base_service)
1292 {
1293   DBusMessage *message;
1294   dbus_bool_t retval;
1295   DBusError error;
1296   CheckServiceDeletedData csdd;
1297
1298   message = NULL;
1299   retval = FALSE;
1300   
1301   dbus_error_init (&error);
1302
1303   /* Now we are expecting ServiceDeleted messages for the base
1304    * service and the activated_name.  The base service
1305    * notification is required to come last.
1306    */
1307   csdd.expected_service_name = activated_name;
1308   csdd.failed = FALSE;
1309   bus_test_clients_foreach (check_service_deleted_foreach,
1310                             &csdd);      
1311
1312   if (csdd.failed)
1313     goto out;
1314       
1315   csdd.expected_service_name = base_service;
1316   csdd.failed = FALSE;
1317   bus_test_clients_foreach (check_service_deleted_foreach,
1318                             &csdd);
1319
1320   if (csdd.failed)
1321     goto out;
1322       
1323   if (!check_no_leftovers (context))
1324     {
1325       _dbus_warn ("Messages were left over after verifying results of service exiting\n");
1326       goto out;
1327     }
1328
1329   retval = TRUE;
1330   
1331  out:
1332   if (message)
1333     dbus_message_unref (message);
1334   
1335   return retval;
1336 }
1337
1338 static dbus_bool_t
1339 check_send_exit_to_service (BusContext     *context,
1340                             DBusConnection *connection,
1341                             const char     *service_name,
1342                             const char     *base_service)
1343 {
1344   dbus_bool_t got_error;
1345   DBusMessage *message;
1346   dbus_int32_t serial;
1347   dbus_bool_t retval;
1348   
1349   _dbus_verbose ("Sending exit message to the test service\n");
1350
1351   retval = FALSE;
1352   
1353   /* Kill off the test service by sending it a quit message */
1354   message = dbus_message_new (service_name,
1355                               "org.freedesktop.DBus.TestSuiteExit");
1356       
1357   if (message == NULL)
1358     {
1359       /* Do this again; we still need the service to exit... */
1360       if (!check_send_exit_to_service (context, connection,
1361                                        service_name, base_service))
1362         goto out;
1363       
1364       return TRUE;
1365     }
1366       
1367   if (!dbus_connection_send (connection, message, &serial))
1368     {
1369       dbus_message_unref (message);
1370
1371       /* Do this again; we still need the service to exit... */
1372       if (!check_send_exit_to_service (context, connection,
1373                                        service_name, base_service))
1374         goto out;
1375       
1376       return TRUE;
1377     }
1378
1379   dbus_message_unref (message);
1380   message = NULL;
1381
1382   /* send message */
1383   bus_test_run_clients_loop (TRUE);
1384
1385   /* read it in and write it out to test service */
1386   bus_test_run_bus_loop (context, FALSE);
1387
1388   /* see if we got an error during message bus dispatching */
1389   bus_test_run_clients_loop (FALSE);
1390   message = dbus_connection_borrow_message (connection);
1391   got_error = message != NULL && dbus_message_get_is_error (message);
1392   if (message)
1393     dbus_connection_return_message (connection, message);
1394           
1395   if (!got_error)
1396     {
1397       /* If no error, wait for the test service to exit */
1398       block_connection_until_message_from_bus (context, connection);
1399               
1400       bus_test_run_everything (context);
1401     }
1402
1403   if (got_error)
1404     {
1405       message = pop_message_waiting_for_memory (connection);
1406       _dbus_assert (message != NULL);
1407
1408       if (!dbus_message_get_is_error (message))
1409         {
1410           _dbus_warn ("expecting an error reply to asking test service to exit, got %s\n",
1411                       dbus_message_get_name (message));
1412           goto out;
1413         }
1414       else if (!dbus_message_name_is (message, DBUS_ERROR_NO_MEMORY))
1415         {
1416           _dbus_warn ("not expecting error %s when asking test service to exit\n",
1417                       dbus_message_get_name (message));
1418           goto out;
1419         }
1420
1421       _dbus_verbose ("Got error %s when asking test service to exit\n",
1422                      dbus_message_get_name (message));
1423
1424       /* Do this again; we still need the service to exit... */
1425       if (!check_send_exit_to_service (context, connection,
1426                                        service_name, base_service))
1427         goto out;
1428     }
1429   else
1430     {
1431       if (!check_service_deactivated (context, connection,
1432                                       service_name, base_service))
1433         goto out;
1434     }
1435
1436   retval = TRUE;
1437   
1438  out:
1439   if (message)
1440     dbus_message_unref (message);
1441   
1442   return retval;
1443 }
1444
1445 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
1446
1447 /* returns TRUE if the correct thing happens,
1448  * but the correct thing may include OOM errors.
1449  */
1450 static dbus_bool_t
1451 check_existent_service_activation (BusContext     *context,
1452                                    DBusConnection *connection)
1453 {
1454   DBusMessage *message;
1455   dbus_int32_t serial;
1456   dbus_bool_t retval;
1457   DBusError error;
1458   char *base_service;
1459
1460   base_service = NULL;
1461   
1462   dbus_error_init (&error);
1463   
1464   message = dbus_message_new (DBUS_SERVICE_DBUS,
1465                               DBUS_MESSAGE_ACTIVATE_SERVICE);
1466
1467   if (message == NULL)
1468     return TRUE;
1469
1470   if (!dbus_message_append_args (message,
1471                                  DBUS_TYPE_STRING, EXISTENT_SERVICE_NAME,
1472                                  DBUS_TYPE_UINT32, 0,
1473                                  DBUS_TYPE_INVALID))
1474     {
1475       dbus_message_unref (message);
1476       return TRUE;
1477     }
1478   
1479   if (!dbus_connection_send (connection, message, &serial))
1480     {
1481       dbus_message_unref (message);
1482       return TRUE;
1483     }
1484
1485   dbus_message_unref (message);
1486   message = NULL;
1487
1488   bus_test_run_everything (context);
1489
1490   /* now wait for the message bus to hear back from the activated
1491    * service.
1492    */
1493   block_connection_until_message_from_bus (context, connection);
1494
1495   bus_test_run_everything (context);
1496
1497   if (!dbus_connection_get_is_connected (connection))
1498     {
1499       _dbus_verbose ("connection was disconnected\n");
1500       return TRUE;
1501     }
1502   
1503   retval = FALSE;
1504   
1505   message = pop_message_waiting_for_memory (connection);
1506   if (message == NULL)
1507     {
1508       _dbus_warn ("Did not receive any messages after %s %d on %p\n",
1509                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
1510       goto out;
1511     }
1512
1513   _dbus_verbose ("Received %s on %p after sending %s\n",
1514                  dbus_message_get_name (message), connection,
1515                  DBUS_MESSAGE_ACTIVATE_SERVICE);
1516
1517   if (dbus_message_get_is_error (message))
1518     {
1519       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
1520         {
1521           _dbus_warn ("Message has wrong sender %s\n",
1522                       dbus_message_get_sender (message) ?
1523                       dbus_message_get_sender (message) : "(none)");
1524           goto out;
1525         }
1526       
1527       if (dbus_message_name_is (message,
1528                                 DBUS_ERROR_NO_MEMORY))
1529         {
1530           ; /* good, this is a valid response */
1531         }
1532       else if (dbus_message_name_is (message,
1533                                      DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1534         {
1535           ; /* good, this is expected also */
1536         }
1537       else if (dbus_message_name_is (message,
1538                                      DBUS_ERROR_SPAWN_CHILD_EXITED))
1539         {
1540           ; /* good, this is expected also (child will exit if for example we don't
1541              * have memory to register it)
1542              */
1543         }
1544       else
1545         {
1546           _dbus_warn ("Did not expect error %s\n",
1547                       dbus_message_get_name (message));
1548           goto out;
1549         }
1550     }
1551   else
1552     {
1553       dbus_bool_t got_service_deleted;
1554       
1555       if (!check_base_service_activated (context, connection,
1556                                          message, &base_service))
1557         goto out;
1558
1559       dbus_message_unref (message);
1560       message = NULL;
1561
1562       /* We may need to block here for the test service to exit or finish up */
1563       block_connection_until_message_from_bus (context, connection);
1564       
1565       message = dbus_connection_borrow_message (connection);
1566       if (message == NULL)
1567         {
1568           _dbus_warn ("Did not receive any messages after base service creation notification\n");
1569           goto out;
1570         }
1571
1572       got_service_deleted = dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_DELETED);
1573
1574       dbus_connection_return_message (connection, message);
1575       message = NULL;
1576       
1577       if (got_service_deleted)
1578         {
1579           /* The service started up and got a base address, but then
1580            * failed to register under EXISTENT_SERVICE_NAME
1581            */
1582           CheckServiceDeletedData csdd;
1583           
1584           csdd.expected_service_name = base_service;
1585           csdd.failed = FALSE;
1586           bus_test_clients_foreach (check_service_deleted_foreach,
1587                                     &csdd);
1588
1589           if (csdd.failed)
1590             goto out;
1591
1592           /* Now we should get an error about the service exiting */
1593           block_connection_until_message_from_bus (context, connection);
1594           
1595           /* and process everything again */
1596           bus_test_run_everything (context);
1597           
1598           message = pop_message_waiting_for_memory (connection);
1599           if (message == NULL)
1600             {
1601               _dbus_warn ("Did not get an error from the service %s exiting\n",
1602                           EXISTENT_SERVICE_NAME);
1603               goto out;
1604             }
1605
1606           if (!dbus_message_get_is_error (message))
1607             {
1608               _dbus_warn ("Expected an error due to service exiting, got %s\n",
1609                           dbus_message_get_name (message));
1610               goto out;
1611             }
1612
1613           if (!dbus_message_name_is (message,
1614                                      DBUS_ERROR_SPAWN_CHILD_EXITED))
1615             {
1616               _dbus_warn ("Expected error %s on service exit, got %s instead\n",
1617                           DBUS_ERROR_SPAWN_CHILD_EXITED,
1618                           dbus_message_get_name (message));
1619               goto out;
1620             }
1621         }
1622       else
1623         {
1624           message = pop_message_waiting_for_memory (connection);
1625           if (message == NULL)
1626             {
1627               _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
1628               goto out;
1629             }
1630           
1631           if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
1632                                         base_service, message))
1633             goto out;
1634           
1635           dbus_message_unref (message);
1636           message = NULL;
1637
1638
1639           if (!check_no_leftovers (context))
1640             {
1641               _dbus_warn ("Messages were left over after successful activation\n");
1642               goto out;
1643             }
1644
1645           if (!check_send_exit_to_service (context, connection,
1646                                            EXISTENT_SERVICE_NAME, base_service))
1647             goto out;
1648         }
1649     }
1650
1651   retval = TRUE;
1652   
1653  out:
1654   if (message)
1655     dbus_message_unref (message);
1656
1657   if (base_service)
1658     dbus_free (base_service);
1659   
1660   return retval;
1661 }
1662
1663 typedef struct
1664 {
1665   Check1Func func;
1666   BusContext *context;
1667 } Check1Data;
1668
1669 static dbus_bool_t
1670 check_oom_check1_func (void *data)
1671 {
1672   Check1Data *d = data;
1673
1674   if (! (* d->func) (d->context))
1675     return FALSE;
1676   
1677   if (!check_no_leftovers (d->context))
1678     {
1679       _dbus_warn ("Messages were left over, should be covered by test suite\n");
1680       return FALSE;
1681     }
1682
1683   return TRUE;
1684 }
1685
1686 static void
1687 check1_try_iterations (BusContext *context,
1688                        const char *description,
1689                        Check1Func  func)
1690 {
1691   Check1Data d;
1692
1693   d.func = func;
1694   d.context = context;
1695
1696   if (!_dbus_test_oom_handling (description, check_oom_check1_func,
1697                                 &d))
1698     _dbus_assert_not_reached ("test failed");
1699 }
1700
1701 typedef struct
1702 {
1703   Check2Func func;
1704   BusContext *context;
1705   DBusConnection *connection;
1706 } Check2Data;
1707
1708 static dbus_bool_t
1709 check_oom_check2_func (void *data)
1710 {
1711   Check2Data *d = data;
1712
1713   if (! (* d->func) (d->context, d->connection))
1714     return FALSE;
1715   
1716   if (!check_no_leftovers (d->context))
1717     {
1718       _dbus_warn ("Messages were left over, should be covered by test suite");
1719       return FALSE;
1720     }
1721
1722   return TRUE;
1723 }
1724
1725 static void
1726 check2_try_iterations (BusContext     *context,
1727                        DBusConnection *connection,
1728                        const char     *description,
1729                        Check2Func      func)
1730 {
1731   Check2Data d;
1732
1733   d.func = func;
1734   d.context = context;
1735   d.connection = connection;
1736   
1737   if (!_dbus_test_oom_handling (description, check_oom_check2_func,
1738                                 &d))
1739     _dbus_assert_not_reached ("test failed");
1740 }
1741
1742 dbus_bool_t
1743 bus_dispatch_test (const DBusString *test_data_dir)
1744 {
1745   BusContext *context;
1746   DBusConnection *foo;
1747   DBusConnection *bar;
1748   DBusConnection *baz;
1749   DBusError error;
1750   
1751   context = bus_context_new_test (test_data_dir,
1752                                   "valid-config-files/debug-allow-all.conf");
1753   if (context == NULL)
1754     return FALSE;
1755
1756   dbus_error_init (&error);
1757   
1758   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
1759   if (foo == NULL)
1760     _dbus_assert_not_reached ("could not alloc connection");
1761
1762   if (!bus_setup_debug_client (foo))
1763     _dbus_assert_not_reached ("could not set up connection");
1764
1765   if (!check_hello_message (context, foo))
1766     _dbus_assert_not_reached ("hello message failed");
1767   
1768   bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
1769   if (bar == NULL)
1770     _dbus_assert_not_reached ("could not alloc connection");
1771
1772   if (!bus_setup_debug_client (bar))
1773     _dbus_assert_not_reached ("could not set up connection");
1774
1775   if (!check_hello_message (context, bar))
1776     _dbus_assert_not_reached ("hello message failed");
1777   
1778   baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
1779   if (baz == NULL)
1780     _dbus_assert_not_reached ("could not alloc connection");
1781
1782   if (!bus_setup_debug_client (baz))
1783     _dbus_assert_not_reached ("could not set up connection");
1784
1785   if (!check_hello_message (context, baz))
1786     _dbus_assert_not_reached ("hello message failed");
1787
1788 #if 0
1789   check2_try_iterations (context, foo, "existent_service_activation",
1790                          check_existent_service_activation);
1791 #endif
1792   
1793   check2_try_iterations (context, foo, "nonexistent_service_activation",
1794                          check_nonexistent_service_activation);
1795
1796   check1_try_iterations (context, "create_and_hello",
1797                          check_hello_connection);
1798   
1799   _dbus_verbose ("Disconnecting foo, bar, and baz\n");
1800
1801   kill_client_connection_unchecked (foo);
1802   kill_client_connection_unchecked (bar);
1803   kill_client_connection_unchecked (baz);
1804
1805   bus_context_unref (context);
1806   
1807   return TRUE;
1808 }
1809 #endif /* DBUS_BUILD_TESTS */