f808a8e47744091635c580a875cd07375d774ab0
[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.1
9  * 
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  */
25
26 #include "dispatch.h"
27 #include "connection.h"
28 #include "driver.h"
29 #include "services.h"
30 #include "activation.h"
31 #include "utils.h"
32 #include "bus.h"
33 #include "signals.h"
34 #include "test.h"
35 #include <dbus/dbus-internals.h>
36 #include <string.h>
37
38 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 DBusMessage*
436 borrow_message_waiting_for_memory (DBusConnection *connection)
437 {
438   while (dbus_connection_get_dispatch_status (connection) ==
439          DBUS_DISPATCH_NEED_MEMORY)
440     _dbus_wait_for_memory ();
441
442   return dbus_connection_borrow_message (connection);
443 }
444
445 static void
446 warn_unexpected_real (DBusConnection *connection,
447                       DBusMessage    *message,
448                       const char     *expected,
449                       const char     *function,
450                       int             line)
451 {
452   if (message)
453     _dbus_warn ("%s:%d received message interface \"%s\" member \"%s\" error name \"%s\" on %p, expecting %s\n",
454                 function, line,
455                 dbus_message_get_interface (message) ?
456                 dbus_message_get_interface (message) : "(unset)",
457                 dbus_message_get_member (message) ?
458                 dbus_message_get_member (message) : "(unset)",
459                 dbus_message_get_error_name (message) ?
460                 dbus_message_get_error_name (message) : "(unset)",
461                 connection,
462                 expected);
463   else
464     _dbus_warn ("%s:%d received no message on %p, expecting %s\n",
465                 function, line, connection, expected);
466 }
467
468 #define warn_unexpected(connection, message, expected) \
469   warn_unexpected_real (connection, message, expected, _DBUS_FUNCTION_NAME, __LINE__)
470
471 static void
472 verbose_message_received (DBusConnection *connection,
473                           DBusMessage    *message)
474 {
475   _dbus_verbose ("Received message interface \"%s\" member \"%s\" error name \"%s\" on %p\n",
476                  dbus_message_get_interface (message) ?
477                  dbus_message_get_interface (message) : "(unset)",
478                  dbus_message_get_member (message) ?
479                  dbus_message_get_member (message) : "(unset)",
480                  dbus_message_get_error_name (message) ?
481                  dbus_message_get_error_name (message) : "(unset)",
482                  connection);
483 }
484
485 typedef struct
486 {
487   const char *expected_service_name;
488   dbus_bool_t failed;
489 } CheckServiceDeletedData;
490
491 static dbus_bool_t
492 check_service_deleted_foreach (DBusConnection *connection,
493                                void           *data)
494 {
495   CheckServiceDeletedData *d = data;
496   DBusMessage *message;
497   DBusError error;
498   char *service_name;
499
500   dbus_error_init (&error);
501   d->failed = TRUE;
502   service_name = NULL;
503   
504   message = pop_message_waiting_for_memory (connection);
505   if (message == NULL)
506     {
507       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
508                   connection, "ServiceDeleted");
509       goto out;
510     }
511   else if (!dbus_message_is_signal (message,
512                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
513                                     "ServiceDeleted"))
514     {
515       warn_unexpected (connection, message, "ServiceDeleted");
516
517       goto out;
518     }
519   else
520     {
521       if (!dbus_message_get_args (message, &error,
522                                   DBUS_TYPE_STRING, &service_name,
523                                   DBUS_TYPE_INVALID))
524         {
525           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
526             {
527               _dbus_verbose ("no memory to get service name arg\n");
528             }
529           else
530             {
531               _dbus_assert (dbus_error_is_set (&error));
532               _dbus_warn ("Did not get the expected single string argument\n");
533               goto out;
534             }
535         }
536       else if (strcmp (service_name, d->expected_service_name) != 0)
537         {
538           _dbus_warn ("expected deletion of service %s, got deletion of %s\n",
539                       d->expected_service_name,
540                       service_name);
541           goto out;
542         }
543     }
544
545   d->failed = FALSE;
546   
547  out:
548   dbus_free (service_name);
549   dbus_error_free (&error);
550   
551   if (message)
552     dbus_message_unref (message);
553
554   return !d->failed;
555 }
556
557 static void
558 kill_client_connection (BusContext     *context,
559                         DBusConnection *connection)
560 {
561   char *base_service;
562   const char *s;
563   CheckServiceDeletedData csdd;
564
565   _dbus_verbose ("killing connection %p\n", connection);
566   
567   s = dbus_bus_get_base_service (connection);
568   _dbus_assert (s != NULL);
569
570   while ((base_service = _dbus_strdup (s)) == NULL)
571     _dbus_wait_for_memory ();
572
573   dbus_connection_ref (connection);
574   
575   /* kick in the disconnect handler that unrefs the connection */
576   dbus_connection_disconnect (connection);
577
578   bus_test_run_everything (context);
579   
580   _dbus_assert (bus_test_client_listed (connection));
581   
582   /* Run disconnect handler in test.c */
583   if (bus_connection_dispatch_one_message (connection))
584     _dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
585   
586   _dbus_assert (!dbus_connection_get_is_connected (connection));
587   dbus_connection_unref (connection);
588   connection = NULL;
589   _dbus_assert (!bus_test_client_listed (connection));
590   
591   csdd.expected_service_name = base_service;
592   csdd.failed = FALSE;
593
594   bus_test_clients_foreach (check_service_deleted_foreach,
595                             &csdd);
596
597   dbus_free (base_service);
598   
599   if (csdd.failed)
600     _dbus_assert_not_reached ("didn't get the expected ServiceDeleted messages");
601   
602   if (!check_no_leftovers (context))
603     _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
604 }
605
606 static void
607 kill_client_connection_unchecked (DBusConnection *connection)
608 {
609   /* This kills the connection without expecting it to affect
610    * the rest of the bus.
611    */  
612   _dbus_verbose ("Unchecked kill of connection %p\n", connection);
613
614   dbus_connection_ref (connection);
615   dbus_connection_disconnect (connection);
616   /* dispatching disconnect handler will unref once */
617   if (bus_connection_dispatch_one_message (connection))
618     _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
619
620   _dbus_assert (!bus_test_client_listed (connection));
621   dbus_connection_unref (connection);
622 }
623
624 typedef struct
625 {
626   dbus_bool_t failed;
627 } CheckNoMessagesData;
628
629 static dbus_bool_t
630 check_no_messages_foreach (DBusConnection *connection,
631                            void           *data)
632 {
633   CheckNoMessagesData *d = data;
634   DBusMessage *message;
635
636   message = pop_message_waiting_for_memory (connection);
637   if (message != NULL)
638     {
639       warn_unexpected (connection, message, "no messages");
640
641       d->failed = TRUE;
642     }
643
644   if (message)
645     dbus_message_unref (message);
646   return !d->failed;
647 }
648
649 typedef struct
650 {
651   DBusConnection *skip_connection;
652   const char *expected_service_name;
653   dbus_bool_t failed;
654 } CheckServiceCreatedData;
655
656 static dbus_bool_t
657 check_service_created_foreach (DBusConnection *connection,
658                                void           *data)
659 {
660   CheckServiceCreatedData *d = data;
661   DBusMessage *message;
662   DBusError error;
663   char *service_name;
664
665   if (connection == d->skip_connection)
666     return TRUE;
667
668   dbus_error_init (&error);
669   d->failed = TRUE;
670   service_name = NULL;
671   
672   message = pop_message_waiting_for_memory (connection);
673   if (message == NULL)
674     {
675       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
676                   connection, "ServiceCreated");
677       goto out;
678     }
679   else if (!dbus_message_is_signal (message,
680                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
681                                     "ServiceCreated"))
682     {
683       warn_unexpected (connection, message, "ServiceCreated");
684       goto out;
685     }
686   else
687     {
688       if (!dbus_message_get_args (message, &error,
689                                   DBUS_TYPE_STRING, &service_name,
690                                   DBUS_TYPE_INVALID))
691         {
692           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
693             {
694               _dbus_verbose ("no memory to get service name arg\n");
695             }
696           else
697             {
698               _dbus_assert (dbus_error_is_set (&error));
699               _dbus_warn ("Did not get the expected single string argument\n");
700               goto out;
701             }
702         }
703       else if (strcmp (service_name, d->expected_service_name) != 0)
704         {
705           _dbus_warn ("expected creation of service %s, got creation of %s\n",
706                       d->expected_service_name,
707                       service_name);
708           goto out;
709         }
710     }
711
712   d->failed = FALSE;
713   
714  out:
715   dbus_free (service_name);
716   dbus_error_free (&error);
717   
718   if (message)
719     dbus_message_unref (message);
720
721   return !d->failed;
722 }
723
724 static dbus_bool_t
725 check_no_leftovers (BusContext *context)
726 {
727   CheckNoMessagesData nmd;
728
729   nmd.failed = FALSE;
730   bus_test_clients_foreach (check_no_messages_foreach,
731                             &nmd);
732   
733   if (nmd.failed)
734     return FALSE;
735   else
736     return TRUE;
737 }
738
739 /* returns TRUE if the correct thing happens,
740  * but the correct thing may include OOM errors.
741  */
742 static dbus_bool_t
743 check_hello_message (BusContext     *context,
744                      DBusConnection *connection)
745 {
746   DBusMessage *message;
747   dbus_uint32_t serial;
748   dbus_bool_t retval;
749   DBusError error;
750   char *name;
751   char *acquired;
752
753   retval = FALSE;
754   dbus_error_init (&error);
755   name = NULL;
756   acquired = NULL;
757   message = NULL;
758
759   _dbus_verbose ("check_hello_message for %p\n", connection);
760   
761   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
762                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
763                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
764                                           "Hello");
765
766   if (message == NULL)
767     return TRUE;
768
769   if (!dbus_connection_send (connection, message, &serial))
770     {
771       dbus_message_unref (message);
772       return TRUE;
773     }
774
775   dbus_message_unref (message);
776   message = NULL;
777
778   /* send our message */
779   bus_test_run_clients_loop (TRUE);
780
781   dbus_connection_ref (connection); /* because we may get disconnected */
782   block_connection_until_message_from_bus (context, connection);
783
784   if (!dbus_connection_get_is_connected (connection))
785     {
786       _dbus_verbose ("connection was disconnected\n");
787       
788       dbus_connection_unref (connection);
789       
790       return TRUE;
791     }
792
793   dbus_connection_unref (connection);
794   
795   message = pop_message_waiting_for_memory (connection);
796   if (message == NULL)
797     {
798       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
799                   "Hello", serial, connection);
800       goto out;
801     }
802
803   verbose_message_received (connection, message);
804
805   if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
806     {
807       _dbus_warn ("Message has wrong sender %s\n",
808                   dbus_message_get_sender (message) ?
809                   dbus_message_get_sender (message) : "(none)");
810       goto out;
811     }
812   
813   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
814     {
815       if (dbus_message_is_error (message,
816                                  DBUS_ERROR_NO_MEMORY))
817         {
818           ; /* good, this is a valid response */
819         }
820       else
821         {
822           warn_unexpected (connection, message, "not this error");
823
824           goto out;
825         }
826     }
827   else
828     {
829       CheckServiceCreatedData scd;
830       
831       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
832         {
833           ; /* good, expected */
834         }
835       else
836         {
837           warn_unexpected (connection, message, "method return for Hello");
838
839           goto out;
840         }
841
842     retry_get_hello_name:
843       if (!dbus_message_get_args (message, &error,
844                                   DBUS_TYPE_STRING, &name,
845                                   DBUS_TYPE_INVALID))
846         {
847           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
848             {
849               _dbus_verbose ("no memory to get service name arg from hello\n");
850               dbus_error_free (&error);
851               _dbus_wait_for_memory ();
852               goto retry_get_hello_name;
853             }
854           else
855             {
856               _dbus_assert (dbus_error_is_set (&error));
857               _dbus_warn ("Did not get the expected single string argument to hello\n");
858               goto out;
859             }
860         }
861
862       _dbus_verbose ("Got hello name: %s\n", name);
863
864       while (!dbus_bus_set_base_service (connection, name))
865         _dbus_wait_for_memory ();
866       
867       scd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
868       scd.failed = FALSE;
869       scd.expected_service_name = name;
870       bus_test_clients_foreach (check_service_created_foreach,
871                                 &scd);
872       
873       if (scd.failed)
874         goto out;
875       
876       /* Client should also have gotten ServiceAcquired */
877       dbus_message_unref (message);
878       message = pop_message_waiting_for_memory (connection);
879       if (message == NULL)
880         {
881           _dbus_warn ("Expecting %s, got nothing\n",
882                       "ServiceAcquired");
883           goto out;
884         }
885       
886     retry_get_acquired_name:
887       if (!dbus_message_get_args (message, &error,
888                                   DBUS_TYPE_STRING, &acquired,
889                                   DBUS_TYPE_INVALID))
890         {
891           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
892             {
893               _dbus_verbose ("no memory to get service name arg from acquired\n");
894               dbus_error_free (&error);
895               _dbus_wait_for_memory ();
896               goto retry_get_acquired_name;
897             }
898           else
899             {
900               _dbus_assert (dbus_error_is_set (&error));
901               _dbus_warn ("Did not get the expected single string argument to ServiceAcquired\n");
902               goto out;
903             }
904         }
905
906       _dbus_verbose ("Got acquired name: %s\n", acquired);
907
908       if (strcmp (acquired, name) != 0)
909         {
910           _dbus_warn ("Acquired name is %s but expected %s\n",
911                       acquired, name);
912           goto out;
913         }
914     }
915
916   if (!check_no_leftovers (context))
917     goto out;
918   
919   retval = TRUE;
920   
921  out:
922   dbus_error_free (&error);
923   
924   dbus_free (name);
925   dbus_free (acquired);
926   
927   if (message)
928     dbus_message_unref (message);
929   
930   return retval;
931 }
932
933 /* returns TRUE if the correct thing happens,
934  * but the correct thing may include OOM errors.
935  */
936 static dbus_bool_t
937 check_get_connection_unix_user (BusContext     *context,
938                                 DBusConnection *connection)
939 {
940   DBusMessage *message;
941   dbus_uint32_t serial;
942   dbus_bool_t retval;
943   DBusError error;
944   const char *base_service_name;
945   dbus_uint32_t uid;
946
947   retval = FALSE;
948   dbus_error_init (&error);
949   message = NULL;
950
951   _dbus_verbose ("check_get_connection_unix_user for %p\n", connection);
952   
953   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
954                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
955                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
956                                           "GetConnectionUnixUser");
957
958   if (message == NULL)
959     return TRUE;
960
961   base_service_name = dbus_bus_get_base_service (connection);
962
963   if (!dbus_message_append_args (message, 
964                                  DBUS_TYPE_STRING, base_service_name,
965                                  DBUS_TYPE_INVALID))
966     {
967       dbus_message_unref (message);
968       return TRUE;
969     }
970
971   if (!dbus_connection_send (connection, message, &serial))
972     {
973       dbus_message_unref (message);
974       return TRUE;
975     }
976
977   /* send our message */
978   bus_test_run_clients_loop (TRUE);
979
980   dbus_message_unref (message);
981   message = NULL;
982
983   dbus_connection_ref (connection); /* because we may get disconnected */
984   block_connection_until_message_from_bus (context, connection);
985
986   if (!dbus_connection_get_is_connected (connection))
987     {
988       _dbus_verbose ("connection was disconnected\n");
989       
990       dbus_connection_unref (connection);
991       
992       return TRUE;
993     }
994
995   dbus_connection_unref (connection);
996
997   message = pop_message_waiting_for_memory (connection);
998   if (message == NULL)
999     {
1000       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1001                   "GetConnectionUnixUser", serial, connection);
1002       goto out;
1003     }
1004
1005   verbose_message_received (connection, message);
1006
1007   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1008     {
1009       if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
1010         {
1011           ; /* good, this is a valid response */
1012         }
1013       else
1014         {
1015           warn_unexpected (connection, message, "not this error");
1016
1017           goto out;
1018         }
1019     }
1020   else
1021     {
1022       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1023         {
1024           ; /* good, expected */
1025         }
1026       else
1027         {
1028           warn_unexpected (connection, message,
1029                            "method_return for GetConnectionUnixUser");
1030
1031           goto out;
1032         }
1033
1034     retry_get_property:
1035
1036       if (!dbus_message_get_args (message, &error,
1037                                   DBUS_TYPE_UINT32, &uid,
1038                                   DBUS_TYPE_INVALID))
1039         {
1040           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1041             {
1042               _dbus_verbose ("no memory to get uid by GetConnectionUnixUser\n");
1043               dbus_error_free (&error);
1044               _dbus_wait_for_memory ();
1045               goto retry_get_property;
1046             }
1047           else
1048             {
1049               _dbus_assert (dbus_error_is_set (&error));
1050               _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixUser\n");
1051               goto out;
1052             }
1053         }
1054     }
1055
1056   if (!check_no_leftovers (context))
1057     goto out;
1058
1059   retval = TRUE;
1060
1061  out:
1062   dbus_error_free (&error);
1063   
1064   if (message)
1065     dbus_message_unref (message);
1066   
1067   return retval;
1068 }
1069
1070 /* returns TRUE if the correct thing happens,
1071  * but the correct thing may include OOM errors.
1072  */
1073 static dbus_bool_t
1074 check_get_connection_unix_process_id (BusContext     *context,
1075                                       DBusConnection *connection)
1076 {
1077   DBusMessage *message;
1078   dbus_uint32_t serial;
1079   dbus_bool_t retval;
1080   DBusError error;
1081   const char *base_service_name;
1082   dbus_uint32_t pid;
1083
1084   retval = FALSE;
1085   dbus_error_init (&error);
1086   message = NULL;
1087
1088   _dbus_verbose ("check_get_connection_unix_process_id for %p\n", connection);
1089   
1090   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
1091                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
1092                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
1093                                           "GetConnectionUnixProcessID");
1094
1095   if (message == NULL)
1096     return TRUE;
1097
1098   base_service_name = dbus_bus_get_base_service (connection);
1099
1100   if (!dbus_message_append_args (message, 
1101                                  DBUS_TYPE_STRING, base_service_name,
1102                                  DBUS_TYPE_INVALID))
1103     {
1104       dbus_message_unref (message);
1105       return TRUE;
1106     }
1107
1108   if (!dbus_connection_send (connection, message, &serial))
1109     {
1110       dbus_message_unref (message);
1111       return TRUE;
1112     }
1113
1114   /* send our message */
1115   bus_test_run_clients_loop (TRUE);
1116
1117   dbus_message_unref (message);
1118   message = NULL;
1119
1120   dbus_connection_ref (connection); /* because we may get disconnected */
1121   block_connection_until_message_from_bus (context, connection);
1122
1123   if (!dbus_connection_get_is_connected (connection))
1124     {
1125       _dbus_verbose ("connection was disconnected\n");
1126       
1127       dbus_connection_unref (connection);
1128       
1129       return TRUE;
1130     }
1131
1132   dbus_connection_unref (connection);
1133
1134   message = pop_message_waiting_for_memory (connection);
1135   if (message == NULL)
1136     {
1137       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1138                   "GetConnectionUnixProcessID", serial, connection);
1139       goto out;
1140     }
1141
1142   verbose_message_received (connection, message);
1143
1144   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1145     {
1146       if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
1147         {
1148           ; /* good, this is a valid response */
1149         }
1150       else
1151         {
1152           warn_unexpected (connection, message, "not this error");
1153
1154           goto out;
1155         }
1156     }
1157   else
1158     {
1159       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1160         {
1161           ; /* good, expected */
1162         }
1163       else
1164         {
1165           warn_unexpected (connection, message,
1166                            "method_return for GetConnectionUnixProcessID");
1167
1168           goto out;
1169         }
1170
1171     retry_get_property:
1172
1173       if (!dbus_message_get_args (message, &error,
1174                                   DBUS_TYPE_UINT32, &pid,
1175                                   DBUS_TYPE_INVALID))
1176         {
1177           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1178             {
1179               _dbus_verbose ("no memory to get pid by GetConnectionUnixProcessID\n");
1180               dbus_error_free (&error);
1181               _dbus_wait_for_memory ();
1182               goto retry_get_property;
1183             }
1184           else
1185             {
1186               _dbus_assert (dbus_error_is_set (&error));
1187               _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixProcessID\n");
1188               goto out;
1189             }
1190         } else {
1191
1192           /* test if returned pid is the same as our own pid
1193            *
1194            * @todo It would probably be good to restructure the tests
1195            *       in a way so our parent is the bus that we're testing
1196            *       cause then we can test that the pid returned matches
1197            *       getppid()
1198            */
1199           if (pid != (dbus_uint32_t) _dbus_getpid ())
1200             {
1201               _dbus_assert (dbus_error_is_set (&error));
1202               _dbus_warn ("Result from GetConnectionUnixProcessID is not our own pid\n");
1203               goto out;
1204             }
1205         }
1206     }
1207
1208   if (!check_no_leftovers (context))
1209     goto out;
1210
1211   retval = TRUE;
1212
1213  out:
1214   dbus_error_free (&error);
1215   
1216   if (message)
1217     dbus_message_unref (message);
1218   
1219   return retval;
1220 }
1221
1222 /* returns TRUE if the correct thing happens,
1223  * but the correct thing may include OOM errors.
1224  */
1225 static dbus_bool_t
1226 check_add_match_all (BusContext     *context,
1227                      DBusConnection *connection)
1228 {
1229   DBusMessage *message;
1230   dbus_bool_t retval;
1231   dbus_uint32_t serial;
1232   DBusError error;
1233
1234   retval = FALSE;
1235   dbus_error_init (&error);
1236   message = NULL;
1237
1238   _dbus_verbose ("check_add_match_all for %p\n", connection);
1239   
1240   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
1241                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
1242                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
1243                                           "AddMatch");
1244
1245   if (message == NULL)
1246     return TRUE;
1247
1248   /* empty string match rule matches everything */
1249   if (!dbus_message_append_args (message, DBUS_TYPE_STRING, "",
1250                                  DBUS_TYPE_INVALID))
1251     {
1252       dbus_message_unref (message);
1253       return TRUE;
1254     }
1255   
1256   if (!dbus_connection_send (connection, message, &serial))
1257     {
1258       dbus_message_unref (message);
1259       return TRUE;
1260     }
1261
1262   dbus_message_unref (message);
1263   message = NULL;
1264
1265   /* send our message */
1266   bus_test_run_clients_loop (TRUE);
1267
1268   dbus_connection_ref (connection); /* because we may get disconnected */
1269   block_connection_until_message_from_bus (context, connection);
1270
1271   if (!dbus_connection_get_is_connected (connection))
1272     {
1273       _dbus_verbose ("connection was disconnected\n");
1274       
1275       dbus_connection_unref (connection);
1276       
1277       return TRUE;
1278     }
1279
1280   dbus_connection_unref (connection);
1281   
1282   message = pop_message_waiting_for_memory (connection);
1283   if (message == NULL)
1284     {
1285       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1286                   "AddMatch", serial, connection);
1287       goto out;
1288     }
1289
1290   verbose_message_received (connection, message);
1291
1292   if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
1293     {
1294       _dbus_warn ("Message has wrong sender %s\n",
1295                   dbus_message_get_sender (message) ?
1296                   dbus_message_get_sender (message) : "(none)");
1297       goto out;
1298     }
1299   
1300   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1301     {
1302       if (dbus_message_is_error (message,
1303                                  DBUS_ERROR_NO_MEMORY))
1304         {
1305           ; /* good, this is a valid response */
1306         }
1307       else
1308         {
1309           warn_unexpected (connection, message, "not this error");
1310
1311           goto out;
1312         }
1313     }
1314   else
1315     {
1316       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1317         {
1318           ; /* good, expected */
1319           _dbus_assert (dbus_message_get_reply_serial (message) == serial);
1320         }
1321       else
1322         {
1323           warn_unexpected (connection, message, "method return for AddMatch");
1324
1325           goto out;
1326         }
1327     }
1328
1329   if (!check_no_leftovers (context))
1330     goto out;
1331   
1332   retval = TRUE;
1333   
1334  out:
1335   dbus_error_free (&error);
1336   
1337   if (message)
1338     dbus_message_unref (message);
1339   
1340   return retval;
1341 }
1342
1343 /* returns TRUE if the correct thing happens,
1344  * but the correct thing may include OOM errors.
1345  */
1346 static dbus_bool_t
1347 check_hello_connection (BusContext *context)
1348 {
1349   DBusConnection *connection;
1350   DBusError error;
1351
1352   dbus_error_init (&error);
1353
1354   connection = dbus_connection_open ("debug-pipe:name=test-server", &error);
1355   if (connection == NULL)
1356     {
1357       _DBUS_ASSERT_ERROR_IS_SET (&error);
1358       dbus_error_free (&error);
1359       return TRUE;
1360     }
1361
1362   if (!bus_setup_debug_client (connection))
1363     {
1364       dbus_connection_disconnect (connection);
1365       dbus_connection_unref (connection);
1366       return TRUE;
1367     }
1368
1369   if (!check_hello_message (context, connection))
1370     return FALSE;
1371   
1372   if (dbus_bus_get_base_service (connection) == NULL)
1373     {
1374       /* We didn't successfully register, so we can't
1375        * do the usual kill_client_connection() checks
1376        */
1377       kill_client_connection_unchecked (connection);
1378     }
1379   else
1380     {
1381       if (!check_add_match_all (context, connection))
1382         return FALSE;
1383       
1384       kill_client_connection (context, connection);
1385     }
1386
1387   return TRUE;
1388 }
1389
1390 #define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
1391
1392 /* returns TRUE if the correct thing happens,
1393  * but the correct thing may include OOM errors.
1394  */
1395 static dbus_bool_t
1396 check_nonexistent_service_activation (BusContext     *context,
1397                                       DBusConnection *connection)
1398 {
1399   DBusMessage *message;
1400   dbus_uint32_t serial;
1401   dbus_bool_t retval;
1402   DBusError error;
1403   
1404   dbus_error_init (&error);
1405   
1406   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
1407                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
1408                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
1409                                           "ActivateService");
1410
1411   if (message == NULL)
1412     return TRUE;
1413
1414   if (!dbus_message_append_args (message,
1415                                  DBUS_TYPE_STRING, NONEXISTENT_SERVICE_NAME,
1416                                  DBUS_TYPE_UINT32, 0,
1417                                  DBUS_TYPE_INVALID))
1418     {
1419       dbus_message_unref (message);
1420       return TRUE;
1421     }
1422   
1423   if (!dbus_connection_send (connection, message, &serial))
1424     {
1425       dbus_message_unref (message);
1426       return TRUE;
1427     }
1428
1429   dbus_message_unref (message);
1430   message = NULL;
1431
1432   bus_test_run_everything (context);
1433   block_connection_until_message_from_bus (context, connection);
1434   bus_test_run_everything (context);
1435
1436   if (!dbus_connection_get_is_connected (connection))
1437     {
1438       _dbus_verbose ("connection was disconnected\n");
1439       return TRUE;
1440     }
1441   
1442   retval = FALSE;
1443   
1444   message = pop_message_waiting_for_memory (connection);
1445   if (message == NULL)
1446     {
1447       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1448                   "ActivateService", serial, connection);
1449       goto out;
1450     }
1451
1452   verbose_message_received (connection, message);
1453
1454   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1455     {
1456       if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
1457         {
1458           _dbus_warn ("Message has wrong sender %s\n",
1459                       dbus_message_get_sender (message) ?
1460                       dbus_message_get_sender (message) : "(none)");
1461           goto out;
1462         }
1463       
1464       if (dbus_message_is_error (message,
1465                                  DBUS_ERROR_NO_MEMORY))
1466         {
1467           ; /* good, this is a valid response */
1468         }
1469       else if (dbus_message_is_error (message,
1470                                       DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1471         {
1472           ; /* good, this is expected also */
1473         }
1474       else
1475         {
1476           warn_unexpected (connection, message, "not this error");
1477           goto out;
1478         }
1479     }
1480   else
1481     {
1482       _dbus_warn ("Did not expect to successfully activate %s\n",
1483                   NONEXISTENT_SERVICE_NAME);
1484       goto out;
1485     }
1486
1487   retval = TRUE;
1488   
1489  out:
1490   if (message)
1491     dbus_message_unref (message);
1492   
1493   return retval;
1494 }
1495
1496 /* returns TRUE if the correct thing happens,
1497  * but the correct thing may include OOM errors.
1498  */
1499 static dbus_bool_t
1500 check_nonexistent_service_auto_activation (BusContext     *context,
1501                                            DBusConnection *connection)
1502 {
1503   DBusMessage *message;
1504   dbus_uint32_t serial;
1505   dbus_bool_t retval;
1506   DBusError error;
1507     
1508   dbus_error_init (&error);
1509
1510   message = dbus_message_new_method_call (NONEXISTENT_SERVICE_NAME,
1511                                           "/org/freedesktop/TestSuite",
1512                                           "org.freedesktop.TestSuite",
1513                                           "Echo");
1514   
1515   if (message == NULL)
1516     return TRUE;
1517
1518   dbus_message_set_auto_activation (message, TRUE);
1519  
1520   if (!dbus_connection_send (connection, message, &serial))
1521     {
1522       dbus_message_unref (message);
1523       return TRUE;
1524     }
1525
1526   dbus_message_unref (message);
1527   message = NULL;
1528
1529   bus_test_run_everything (context);
1530   block_connection_until_message_from_bus (context, connection);
1531   bus_test_run_everything (context);
1532
1533   if (!dbus_connection_get_is_connected (connection))
1534     {
1535       _dbus_verbose ("connection was disconnected\n");
1536       return TRUE;
1537     }
1538   
1539   retval = FALSE;
1540   
1541   message = pop_message_waiting_for_memory (connection);
1542
1543   if (message == NULL)
1544     {
1545       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1546                   "Echo message (auto activation)", serial, connection);
1547       goto out;
1548     }
1549
1550   verbose_message_received (connection, message);
1551
1552   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1553     {
1554       if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
1555         {
1556           _dbus_warn ("Message has wrong sender %s\n",
1557                       dbus_message_get_sender (message) ?
1558                       dbus_message_get_sender (message) : "(none)");
1559           goto out;
1560         }
1561       
1562       if (dbus_message_is_error (message,
1563                                  DBUS_ERROR_NO_MEMORY))
1564         {
1565           ; /* good, this is a valid response */
1566         }
1567       else if (dbus_message_is_error (message,
1568                                       DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1569         {
1570           ; /* good, this is expected also */
1571         }
1572       else
1573         {
1574           warn_unexpected (connection, message, "not this error");
1575           goto out;
1576         }
1577     }
1578   else
1579     {
1580       _dbus_warn ("Did not expect to successfully activate %s\n",
1581                   NONEXISTENT_SERVICE_NAME);
1582       goto out;
1583     }
1584
1585   retval = TRUE;
1586   
1587  out:
1588   if (message)
1589     dbus_message_unref (message);
1590   
1591   return retval;
1592 }
1593
1594 static dbus_bool_t
1595 check_base_service_activated (BusContext     *context,
1596                               DBusConnection *connection,
1597                               DBusMessage    *initial_message,
1598                               char          **base_service_p)
1599 {
1600   DBusMessage *message;
1601   dbus_bool_t retval;
1602   DBusError error;
1603   char *base_service;
1604   
1605   base_service = NULL;
1606   retval = FALSE;
1607   
1608   dbus_error_init (&error);
1609
1610   message = initial_message;
1611   dbus_message_ref (message);  
1612
1613   if (dbus_message_is_signal (message,
1614                               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
1615                               "ServiceCreated"))
1616     {
1617       char *service_name;
1618       CheckServiceCreatedData scd;
1619
1620     reget_service_name_arg:
1621       if (!dbus_message_get_args (message, &error,
1622                                   DBUS_TYPE_STRING, &service_name,
1623                                   DBUS_TYPE_INVALID))
1624         {
1625           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1626             {
1627               dbus_error_free (&error);
1628               _dbus_wait_for_memory ();
1629               goto reget_service_name_arg;
1630             }
1631           else
1632             {
1633               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1634                           "ServiceCreated",
1635                           error.message);
1636               dbus_error_free (&error);
1637               goto out;
1638             }
1639         }
1640
1641       if (*service_name != ':')
1642         {
1643           _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
1644                       service_name);
1645           goto out;
1646         }
1647               
1648       base_service = service_name;
1649       service_name = NULL;
1650       
1651       scd.skip_connection = connection;
1652       scd.failed = FALSE;
1653       scd.expected_service_name = base_service;
1654       bus_test_clients_foreach (check_service_created_foreach,
1655                                 &scd);
1656       
1657       if (scd.failed)
1658         goto out;
1659     }
1660   else
1661     {
1662       warn_unexpected (connection, message, "ServiceCreated for base service");
1663
1664       goto out;
1665     }
1666
1667   retval = TRUE;
1668
1669   if (base_service_p)
1670     {
1671       *base_service_p = base_service;
1672       base_service = NULL;
1673     }
1674   
1675  out:
1676   if (message)
1677     dbus_message_unref (message);
1678
1679   if (base_service)
1680     dbus_free (base_service);
1681   
1682   return retval;
1683 }
1684
1685 static dbus_bool_t
1686 check_service_activated (BusContext     *context,
1687                          DBusConnection *connection,
1688                          const char     *activated_name,
1689                          const char     *base_service_name,
1690                          DBusMessage    *initial_message)
1691 {
1692   DBusMessage *message;
1693   dbus_bool_t retval;
1694   DBusError error;
1695   dbus_uint32_t activation_result;
1696   
1697   retval = FALSE;
1698   
1699   dbus_error_init (&error);
1700
1701   message = initial_message;
1702   dbus_message_ref (message);
1703
1704   if (dbus_message_is_signal (message,
1705                               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
1706                               "ServiceCreated"))
1707     {
1708       char *service_name;
1709       CheckServiceCreatedData scd;
1710
1711     reget_service_name_arg:
1712       if (!dbus_message_get_args (message, &error,
1713                                   DBUS_TYPE_STRING, &service_name,
1714                                   DBUS_TYPE_INVALID))
1715         {
1716           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1717             {
1718               dbus_error_free (&error);
1719               _dbus_wait_for_memory ();
1720               goto reget_service_name_arg;
1721             }
1722           else
1723             {
1724               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1725                           "ServiceCreated",
1726                           error.message);
1727               dbus_error_free (&error);
1728               goto out;
1729             }
1730         }
1731
1732       if (strcmp (service_name, activated_name) != 0)
1733         {
1734           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
1735                       activated_name, service_name);
1736           dbus_free (service_name);
1737           goto out;
1738         }
1739       
1740       scd.skip_connection = connection;
1741       scd.failed = FALSE;
1742       scd.expected_service_name = service_name;
1743       bus_test_clients_foreach (check_service_created_foreach,
1744                                 &scd);
1745           
1746       dbus_free (service_name);
1747
1748       if (scd.failed)
1749         goto out;
1750           
1751       dbus_message_unref (message);
1752       message = pop_message_waiting_for_memory (connection);
1753       if (message == NULL)
1754         {
1755           _dbus_warn ("Expected a reply to %s, got nothing\n",
1756                       "ActivateService");
1757           goto out;
1758         }
1759     }
1760   else
1761     {
1762       warn_unexpected (connection, message, "ServiceCreated for the activated name");
1763       
1764       goto out;
1765     }
1766   
1767   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
1768     {
1769       warn_unexpected (connection, message, "reply to ActivateService");
1770
1771       goto out;
1772     }
1773
1774   activation_result = 0;
1775   if (!dbus_message_get_args (message, &error,
1776                               DBUS_TYPE_UINT32, &activation_result,
1777                               DBUS_TYPE_INVALID))
1778     {
1779       if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1780         {
1781           _dbus_warn ("Did not have activation result first argument to %s: %s\n",
1782                       "ActivateService", error.message);
1783           dbus_error_free (&error);
1784           goto out;
1785         }
1786
1787       dbus_error_free (&error);
1788     }
1789   else
1790     {
1791       if (activation_result == DBUS_ACTIVATION_REPLY_ACTIVATED)
1792         ; /* Good */
1793       else if (activation_result == DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE)
1794         ; /* Good also */
1795       else
1796         {
1797           _dbus_warn ("Activation result was 0x%x, no good.\n",
1798                       activation_result);
1799           goto out;
1800         }
1801     }
1802
1803   dbus_message_unref (message);
1804   message = NULL;
1805       
1806   if (!check_no_leftovers (context))
1807     {
1808       _dbus_warn ("Messages were left over after verifying existent activation results\n");
1809       goto out;
1810     }
1811
1812   retval = TRUE;
1813   
1814  out:
1815   if (message)
1816     dbus_message_unref (message);
1817   
1818   return retval;
1819 }
1820
1821 static dbus_bool_t
1822 check_service_auto_activated (BusContext     *context,
1823                               DBusConnection *connection,
1824                               const char     *activated_name,
1825                               const char     *base_service_name,
1826                               DBusMessage    *initial_message)
1827 {
1828   DBusMessage *message;
1829   dbus_bool_t retval;
1830   DBusError error;
1831   
1832   retval = FALSE;
1833   
1834   dbus_error_init (&error);
1835
1836   message = initial_message;
1837   dbus_message_ref (message);
1838
1839   if (dbus_message_is_signal (message,
1840                               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
1841                               "ServiceCreated"))
1842     {
1843       char *service_name;
1844       CheckServiceCreatedData scd;
1845       
1846     reget_service_name_arg:
1847       if (!dbus_message_get_args (message, &error,
1848                                   DBUS_TYPE_STRING, &service_name,
1849                                   DBUS_TYPE_INVALID))
1850         {
1851           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1852             {
1853               dbus_error_free (&error);
1854               _dbus_wait_for_memory ();
1855               goto reget_service_name_arg;
1856             }
1857           else
1858             {
1859               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1860                           "ServiceCreated",
1861                           error.message);
1862               dbus_error_free (&error);
1863               goto out;
1864             }
1865         }
1866       
1867       if (strcmp (service_name, activated_name) != 0)
1868         {
1869           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
1870                       activated_name, service_name);
1871           dbus_free (service_name);
1872           goto out;
1873         }
1874       
1875       scd.skip_connection = connection;
1876       scd.failed = FALSE;
1877       scd.expected_service_name = service_name;
1878       bus_test_clients_foreach (check_service_created_foreach,
1879                                 &scd);
1880       
1881       dbus_free (service_name);
1882       
1883       if (scd.failed)
1884         goto out;
1885       
1886       /* Note that this differs from regular activation in that we don't get a
1887        * reply to ActivateService here.
1888        */
1889       
1890       dbus_message_unref (message);
1891       message = NULL;
1892     }
1893   else
1894     {
1895       warn_unexpected (connection, message, "ServiceCreated for the activated name");
1896       
1897       goto out;
1898     }
1899   
1900   retval = TRUE;
1901   
1902  out:
1903   if (message)
1904     dbus_message_unref (message);
1905   
1906   return retval;
1907 }
1908
1909 static dbus_bool_t
1910 check_service_deactivated (BusContext     *context,
1911                            DBusConnection *connection,
1912                            const char     *activated_name,
1913                            const char     *base_service)
1914 {
1915   dbus_bool_t retval;
1916   CheckServiceDeletedData csdd;
1917
1918   retval = FALSE;
1919   
1920   /* Now we are expecting ServiceDeleted messages for the base
1921    * service and the activated_name.  The base service
1922    * notification is required to come last.
1923    */
1924   csdd.expected_service_name = activated_name;
1925   csdd.failed = FALSE;
1926   bus_test_clients_foreach (check_service_deleted_foreach,
1927                             &csdd);      
1928
1929   if (csdd.failed)
1930     goto out;
1931       
1932   csdd.expected_service_name = base_service;
1933   csdd.failed = FALSE;
1934   bus_test_clients_foreach (check_service_deleted_foreach,
1935                             &csdd);
1936
1937   if (csdd.failed)
1938     goto out;
1939
1940   retval = TRUE;
1941   
1942  out:
1943   return retval;
1944 }
1945
1946 static dbus_bool_t
1947 check_send_exit_to_service (BusContext     *context,
1948                             DBusConnection *connection,
1949                             const char     *service_name,
1950                             const char     *base_service)
1951 {
1952   dbus_bool_t got_error;
1953   DBusMessage *message;
1954   dbus_uint32_t serial;
1955   dbus_bool_t retval;
1956   
1957   _dbus_verbose ("Sending exit message to the test service\n");
1958
1959   retval = FALSE;
1960   
1961   /* Kill off the test service by sending it a quit message */
1962   message = dbus_message_new_method_call (service_name,
1963                                           "/org/freedesktop/TestSuite",
1964                                           "org.freedesktop.TestSuite",
1965                                           "Exit");
1966       
1967   if (message == NULL)
1968     {
1969       /* Do this again; we still need the service to exit... */
1970       if (!check_send_exit_to_service (context, connection,
1971                                        service_name, base_service))
1972         goto out;
1973       
1974       return TRUE;
1975     }
1976       
1977   if (!dbus_connection_send (connection, message, &serial))
1978     {
1979       dbus_message_unref (message);
1980
1981       /* Do this again; we still need the service to exit... */
1982       if (!check_send_exit_to_service (context, connection,
1983                                        service_name, base_service))
1984         goto out;
1985       
1986       return TRUE;
1987     }
1988
1989   dbus_message_unref (message);
1990   message = NULL;
1991
1992   /* send message */
1993   bus_test_run_clients_loop (TRUE);
1994
1995   /* read it in and write it out to test service */
1996   bus_test_run_bus_loop (context, FALSE);
1997
1998   /* see if we got an error during message bus dispatching */
1999   bus_test_run_clients_loop (FALSE);
2000   message = borrow_message_waiting_for_memory (connection);
2001   got_error = message != NULL && dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
2002   if (message)
2003     {
2004       dbus_connection_return_message (connection, message);
2005       message = NULL;
2006     }
2007           
2008   if (!got_error)
2009     {
2010       /* If no error, wait for the test service to exit */
2011       block_connection_until_message_from_bus (context, connection);
2012               
2013       bus_test_run_everything (context);
2014     }
2015
2016   if (got_error)
2017     {
2018       message = pop_message_waiting_for_memory (connection);
2019       _dbus_assert (message != NULL);
2020
2021       if (dbus_message_get_reply_serial (message) != serial)
2022         {
2023           warn_unexpected (connection, message,
2024                            "error with the correct reply serial");
2025           goto out;
2026         }
2027       
2028       if (!dbus_message_is_error (message,
2029                                   DBUS_ERROR_NO_MEMORY))
2030         {
2031           warn_unexpected (connection, message,
2032                            "a no memory error from asking test service to exit");
2033           goto out;
2034         }
2035
2036       _dbus_verbose ("Got error %s when asking test service to exit\n",
2037                      dbus_message_get_error_name (message));
2038
2039       /* Do this again; we still need the service to exit... */
2040       if (!check_send_exit_to_service (context, connection,
2041                                        service_name, base_service))
2042         goto out;
2043     }
2044   else
2045     {
2046       if (!check_service_deactivated (context, connection,
2047                                       service_name, base_service))
2048         goto out;
2049
2050       /* Should now have a NoReply error from the Exit() method
2051        * call; it should have come after all the deactivation
2052        * stuff.
2053        */
2054       message = pop_message_waiting_for_memory (connection);
2055           
2056       if (message == NULL)
2057         {
2058           warn_unexpected (connection, NULL,
2059                            "reply to Exit() method call");
2060           goto out;
2061         }
2062       if (!dbus_message_is_error (message,
2063                                   DBUS_ERROR_NO_REPLY))
2064         {
2065           warn_unexpected (connection, NULL,
2066                            "NoReply error from Exit() method call");
2067           goto out;
2068         }
2069
2070       if (dbus_message_get_reply_serial (message) != serial)
2071         {
2072           warn_unexpected (connection, message,
2073                            "error with the correct reply serial");
2074           goto out;
2075         }
2076           
2077       _dbus_verbose ("Got error %s after test service exited\n",
2078                      dbus_message_get_error_name (message));
2079       
2080       if (!check_no_leftovers (context))
2081         {
2082           _dbus_warn ("Messages were left over after %s\n",
2083                       _DBUS_FUNCTION_NAME);
2084           goto out;
2085         }
2086     }
2087   
2088   retval = TRUE;
2089   
2090  out:
2091   if (message)
2092     dbus_message_unref (message);
2093   
2094   return retval;
2095 }
2096
2097 static dbus_bool_t
2098 check_got_error (BusContext     *context,
2099                  DBusConnection *connection,
2100                  const char     *first_error_name,
2101                  ...)
2102 {
2103   DBusMessage *message;
2104   dbus_bool_t retval;
2105   va_list ap;
2106   dbus_bool_t error_found;
2107   const char *error_name;
2108   
2109   retval = FALSE;
2110   
2111   message = pop_message_waiting_for_memory (connection);
2112   if (message == NULL)
2113     {
2114       _dbus_warn ("Did not get an expected error\n");
2115       goto out;
2116     }
2117
2118   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
2119     {
2120       warn_unexpected (connection, message, "an error");
2121
2122       goto out;
2123     }
2124
2125   error_found = FALSE;
2126
2127   va_start (ap, first_error_name);
2128   error_name = first_error_name;
2129   while (error_name != NULL)
2130     {
2131       if (dbus_message_is_error (message, error_name))
2132         {
2133           error_found = TRUE;
2134           break;
2135         }
2136       error_name = va_arg (ap, char*);
2137     }
2138   va_end (ap);
2139
2140   if (!error_found)
2141     {
2142       _dbus_warn ("Expected error %s or other, got %s instead\n",
2143                   first_error_name,
2144                   dbus_message_get_error_name (message));
2145       goto out;
2146     }
2147
2148   retval = TRUE;
2149   
2150  out:
2151   if (message)
2152     dbus_message_unref (message);
2153   
2154   return retval;
2155 }
2156           
2157 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
2158
2159 /* returns TRUE if the correct thing happens,
2160  * but the correct thing may include OOM errors.
2161  */
2162 static dbus_bool_t
2163 check_existent_service_activation (BusContext     *context,
2164                                    DBusConnection *connection)
2165 {
2166   DBusMessage *message;
2167   dbus_uint32_t serial;
2168   dbus_bool_t retval;
2169   DBusError error;
2170   char *base_service;
2171
2172   base_service = NULL;
2173   
2174   dbus_error_init (&error);
2175   
2176   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
2177                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
2178                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
2179                                           "ActivateService");
2180
2181   if (message == NULL)
2182     return TRUE;
2183
2184   if (!dbus_message_append_args (message,
2185                                  DBUS_TYPE_STRING, EXISTENT_SERVICE_NAME,
2186                                  DBUS_TYPE_UINT32, 0,
2187                                  DBUS_TYPE_INVALID))
2188     {
2189       dbus_message_unref (message);
2190       return TRUE;
2191     }
2192   
2193   if (!dbus_connection_send (connection, message, &serial))
2194     {
2195       dbus_message_unref (message);
2196       return TRUE;
2197     }
2198
2199   dbus_message_unref (message);
2200   message = NULL;
2201
2202   bus_test_run_everything (context);
2203
2204   /* now wait for the message bus to hear back from the activated
2205    * service.
2206    */
2207   block_connection_until_message_from_bus (context, connection);
2208
2209   bus_test_run_everything (context);
2210
2211   if (!dbus_connection_get_is_connected (connection))
2212     {
2213       _dbus_verbose ("connection was disconnected\n");
2214       return TRUE;
2215     }
2216   
2217   retval = FALSE;
2218   
2219   message = pop_message_waiting_for_memory (connection);
2220   if (message == NULL)
2221     {
2222       _dbus_warn ("Did not receive any messages after %s %d on %p\n",
2223                   "ActivateService", serial, connection);
2224       goto out;
2225     }
2226
2227   verbose_message_received (connection, message);
2228   _dbus_verbose ("  (after sending %s)\n", "ActivateService");
2229
2230   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2231     {
2232       if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
2233         {
2234           _dbus_warn ("Message has wrong sender %s\n",
2235                       dbus_message_get_sender (message) ?
2236                       dbus_message_get_sender (message) : "(none)");
2237           goto out;
2238         }
2239       
2240       if (dbus_message_is_error (message,
2241                                  DBUS_ERROR_NO_MEMORY))
2242         {
2243           ; /* good, this is a valid response */
2244         }
2245       else if (dbus_message_is_error (message,
2246                                       DBUS_ERROR_SPAWN_CHILD_EXITED))
2247         {
2248           ; /* good, this is expected also */
2249         }
2250       else
2251         {
2252           _dbus_warn ("Did not expect error %s\n",
2253                       dbus_message_get_error_name (message));
2254           goto out;
2255         }
2256     }
2257   else
2258     {
2259       dbus_bool_t got_service_deleted;
2260       dbus_bool_t got_error;
2261       
2262       if (!check_base_service_activated (context, connection,
2263                                          message, &base_service))
2264         goto out;
2265
2266       dbus_message_unref (message);
2267       message = NULL;
2268
2269       /* We may need to block here for the test service to exit or finish up */
2270       block_connection_until_message_from_bus (context, connection);
2271       
2272       message = dbus_connection_borrow_message (connection);
2273       if (message == NULL)
2274         {
2275           _dbus_warn ("Did not receive any messages after base service creation notification\n");
2276           goto out;
2277         }
2278
2279       got_service_deleted = dbus_message_is_signal (message,
2280                                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
2281                                                     "ServiceDeleted");
2282       got_error = dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
2283       
2284       dbus_connection_return_message (connection, message);
2285       message = NULL;
2286
2287       if (got_error)
2288         {
2289           if (!check_got_error (context, connection,
2290                                 DBUS_ERROR_SPAWN_CHILD_EXITED,
2291                                 DBUS_ERROR_NO_MEMORY,
2292                                 NULL))
2293             goto out;
2294
2295           /* A service deleted should be coming along now after this error.
2296            * We can also get the error *after* the service deleted.
2297            */
2298           got_service_deleted = TRUE;
2299         }
2300       
2301       if (got_service_deleted)
2302         {
2303           /* The service started up and got a base address, but then
2304            * failed to register under EXISTENT_SERVICE_NAME
2305            */
2306           CheckServiceDeletedData csdd;
2307           
2308           csdd.expected_service_name = base_service;
2309           csdd.failed = FALSE;
2310           bus_test_clients_foreach (check_service_deleted_foreach,
2311                                     &csdd);
2312
2313           if (csdd.failed)
2314             goto out;
2315
2316           /* Now we should get an error about the service exiting
2317            * if we didn't get it before.
2318            */
2319           if (!got_error)
2320             {
2321               block_connection_until_message_from_bus (context, connection);
2322               
2323               /* and process everything again */
2324               bus_test_run_everything (context);
2325               
2326               if (!check_got_error (context, connection,
2327                                     DBUS_ERROR_SPAWN_CHILD_EXITED,
2328                                     NULL))
2329                 goto out;
2330             }
2331         }
2332       else
2333         {
2334           message = pop_message_waiting_for_memory (connection);
2335           if (message == NULL)
2336             {
2337               _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
2338               goto out;
2339             }
2340           
2341           if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
2342                                         base_service, message))
2343             goto out;
2344           
2345           dbus_message_unref (message);
2346           message = NULL;
2347
2348
2349           if (!check_no_leftovers (context))
2350             {
2351               _dbus_warn ("Messages were left over after successful activation\n");
2352               goto out;
2353             }
2354
2355           if (!check_send_exit_to_service (context, connection,
2356                                            EXISTENT_SERVICE_NAME, base_service))
2357             goto out;
2358         }
2359     }
2360   
2361   retval = TRUE;
2362   
2363  out:
2364   if (message)
2365     dbus_message_unref (message);
2366
2367   if (base_service)
2368     dbus_free (base_service);
2369   
2370   return retval;
2371 }
2372
2373 /* returns TRUE if the correct thing happens,
2374  * but the correct thing may include OOM errors.
2375  */
2376 static dbus_bool_t
2377 check_segfault_service_activation (BusContext     *context,
2378                                    DBusConnection *connection)
2379 {
2380   DBusMessage *message;
2381   dbus_uint32_t serial;
2382   dbus_bool_t retval;
2383   DBusError error;
2384   
2385   dbus_error_init (&error);
2386   
2387   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
2388                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
2389                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
2390                                           "ActivateService");
2391
2392   if (message == NULL)
2393     return TRUE;
2394
2395   if (!dbus_message_append_args (message,
2396                                  DBUS_TYPE_STRING,
2397                                  "org.freedesktop.DBus.TestSuiteSegfaultService",
2398                                  DBUS_TYPE_UINT32, 0,
2399                                  DBUS_TYPE_INVALID))
2400     {
2401       dbus_message_unref (message);
2402       return TRUE;
2403     }
2404   
2405   if (!dbus_connection_send (connection, message, &serial))
2406     {
2407       dbus_message_unref (message);
2408       return TRUE;
2409     }
2410
2411   dbus_message_unref (message);
2412   message = NULL;
2413
2414   bus_test_run_everything (context);
2415   block_connection_until_message_from_bus (context, connection);
2416   bus_test_run_everything (context);
2417
2418   if (!dbus_connection_get_is_connected (connection))
2419     {
2420       _dbus_verbose ("connection was disconnected\n");
2421       return TRUE;
2422     }
2423   
2424   retval = FALSE;
2425   
2426   message = pop_message_waiting_for_memory (connection);
2427   if (message == NULL)
2428     {
2429       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
2430                   "ActivateService", serial, connection);
2431       goto out;
2432     }
2433
2434   verbose_message_received (connection, message);
2435
2436   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2437     {
2438       if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
2439         {
2440           _dbus_warn ("Message has wrong sender %s\n",
2441                       dbus_message_get_sender (message) ?
2442                       dbus_message_get_sender (message) : "(none)");
2443           goto out;
2444         }
2445       
2446       if (dbus_message_is_error (message,
2447                                  DBUS_ERROR_NO_MEMORY))
2448         {
2449           ; /* good, this is a valid response */
2450         }
2451       else if (dbus_message_is_error (message,
2452                                       DBUS_ERROR_SPAWN_CHILD_SIGNALED))
2453         {
2454           ; /* good, this is expected also */
2455         }
2456       else
2457         {
2458           warn_unexpected (connection, message, "not this error");
2459
2460           goto out;
2461         }
2462     }
2463   else
2464     {
2465       _dbus_warn ("Did not expect to successfully activate segfault service\n");
2466       goto out;
2467     }
2468
2469   retval = TRUE;
2470   
2471  out:
2472   if (message)
2473     dbus_message_unref (message);
2474   
2475   return retval;
2476 }
2477
2478
2479 /* returns TRUE if the correct thing happens,
2480  * but the correct thing may include OOM errors.
2481  */
2482 static dbus_bool_t
2483 check_segfault_service_auto_activation (BusContext     *context,
2484                                         DBusConnection *connection)
2485 {
2486   DBusMessage *message;
2487   dbus_uint32_t serial;
2488   dbus_bool_t retval;
2489   DBusError error;
2490
2491   dbus_error_init (&error);
2492
2493   dbus_error_init (&error);
2494
2495   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteSegfaultService",
2496                                           "/org/freedesktop/TestSuite",
2497                                           "org.freedesktop.TestSuite",
2498                                           "Echo");
2499   
2500   if (message == NULL)
2501     return TRUE;
2502
2503   dbus_message_set_auto_activation (message, TRUE);
2504   
2505   if (!dbus_connection_send (connection, message, &serial))
2506     {
2507       dbus_message_unref (message);
2508       return TRUE;
2509     }
2510
2511   dbus_message_unref (message);
2512   message = NULL;
2513
2514   bus_test_run_everything (context);
2515   block_connection_until_message_from_bus (context, connection);
2516   bus_test_run_everything (context);
2517
2518   if (!dbus_connection_get_is_connected (connection))
2519     {
2520       _dbus_verbose ("connection was disconnected\n");
2521       return TRUE;
2522     }
2523   
2524   retval = FALSE;
2525   
2526   message = pop_message_waiting_for_memory (connection);
2527   if (message == NULL)
2528     {
2529       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
2530                   "Echo message (auto activation)", serial, connection);
2531       goto out;
2532     }
2533
2534   verbose_message_received (connection, message);
2535
2536   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2537     {
2538       if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
2539         {
2540           _dbus_warn ("Message has wrong sender %s\n",
2541                       dbus_message_get_sender (message) ?
2542                       dbus_message_get_sender (message) : "(none)");
2543           goto out;
2544         }
2545       
2546       if (dbus_message_is_error (message,
2547                                  DBUS_ERROR_NO_MEMORY))
2548         {
2549           ; /* good, this is a valid response */
2550         }
2551       else if (dbus_message_is_error (message,
2552                                       DBUS_ERROR_SPAWN_CHILD_SIGNALED))
2553         {
2554           ; /* good, this is expected also */
2555         }
2556       else
2557         {
2558           warn_unexpected (connection, message, "not this error");
2559
2560           goto out;
2561         }
2562     }
2563   else
2564     {
2565       _dbus_warn ("Did not expect to successfully activate segfault service\n");
2566       goto out;
2567     }
2568
2569   retval = TRUE;
2570   
2571  out:
2572   if (message)
2573     dbus_message_unref (message);
2574   
2575   return retval;
2576 }
2577
2578 #define TEST_ECHO_MESSAGE "Test echo message"
2579
2580 /* returns TRUE if the correct thing happens,
2581  * but the correct thing may include OOM errors.
2582  */
2583 static dbus_bool_t
2584 check_existent_service_auto_activation (BusContext     *context,
2585                                         DBusConnection *connection)
2586 {
2587   DBusMessage *message;
2588   dbus_uint32_t serial;
2589   dbus_bool_t retval;
2590   DBusError error;
2591   char *base_service;
2592
2593   base_service = NULL;
2594
2595   dbus_error_init (&error);
2596
2597   message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
2598                                           "/org/freedesktop/TestSuite",
2599                                           "org.freedesktop.TestSuite",
2600                                           "Echo");
2601   
2602   if (message == NULL)
2603     return TRUE;
2604
2605   dbus_message_set_auto_activation (message, TRUE);
2606
2607   if (!dbus_message_append_args (message,
2608                                  DBUS_TYPE_STRING, TEST_ECHO_MESSAGE,
2609                                  DBUS_TYPE_INVALID))
2610     {
2611       dbus_message_unref (message);
2612       return TRUE;
2613     }
2614
2615   if (!dbus_connection_send (connection, message, &serial))
2616     {
2617       dbus_message_unref (message);
2618       return TRUE;
2619     }
2620
2621   dbus_message_unref (message);
2622   message = NULL;
2623
2624   bus_test_run_everything (context);
2625
2626   /* now wait for the message bus to hear back from the activated
2627    * service.
2628    */
2629   block_connection_until_message_from_bus (context, connection);
2630   bus_test_run_everything (context);
2631
2632   if (!dbus_connection_get_is_connected (connection))
2633     {
2634       _dbus_verbose ("connection was disconnected\n");
2635       return TRUE;
2636     }
2637
2638   retval = FALSE;
2639   
2640   /* Should get ServiceCreated for the base service, or an error. */
2641   message = pop_message_waiting_for_memory (connection);
2642   if (message == NULL)
2643     {
2644       _dbus_warn ("Did not receive any messages after auto activation %d on %p\n",
2645                   serial, connection);
2646       goto out;
2647     }
2648
2649   verbose_message_received (connection, message);
2650   _dbus_verbose ("  (after sending %s)\n", "ActivateService");
2651
2652   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2653     {
2654       if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
2655         {
2656           _dbus_warn ("Message has wrong sender %s\n",
2657                       dbus_message_get_sender (message) ?
2658                       dbus_message_get_sender (message) : "(none)");
2659           goto out;
2660         }
2661
2662       if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY) ||
2663           dbus_message_is_error (message, DBUS_ERROR_SPAWN_CHILD_EXITED) ||
2664           dbus_message_is_error (message, DBUS_ERROR_TIMED_OUT))
2665         {
2666           ; /* good, those are expected */
2667           retval = TRUE;
2668           goto out;
2669         }
2670       else
2671         {
2672           _dbus_warn ("Did not expect error %s\n",
2673                       dbus_message_get_error_name (message));
2674           goto out;
2675         }
2676     }
2677   else
2678     {
2679       dbus_bool_t got_service_deleted;
2680       dbus_bool_t got_error;
2681       
2682       if (!check_base_service_activated (context, connection,
2683                                          message, &base_service))
2684         goto out;
2685
2686       dbus_message_unref (message);
2687       message = NULL;
2688
2689       /* We may need to block here for the test service to exit or finish up */
2690       block_connection_until_message_from_bus (context, connection);
2691
2692       /* Should get ServiceCreated for the activated service name,
2693        * ServiceDeleted on the base service name, or an error.
2694        */
2695       message = dbus_connection_borrow_message (connection);
2696       if (message == NULL)
2697         {
2698           _dbus_warn ("Did not receive any messages after base service creation notification\n");
2699           goto out;
2700         }
2701
2702       got_service_deleted = dbus_message_is_signal (message,
2703                                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
2704                                                     "ServiceDeleted");
2705       got_error = dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
2706
2707       dbus_connection_return_message (connection, message);
2708       message = NULL;
2709
2710       if (got_error)
2711         {
2712           if (!check_got_error (context, connection,
2713                                 DBUS_ERROR_SPAWN_CHILD_EXITED,
2714                                 DBUS_ERROR_NO_MEMORY,
2715                                 NULL))
2716             goto out;
2717
2718           /* A service deleted should be coming along now after this error.
2719            * We can also get the error *after* the service deleted.
2720            */
2721           got_service_deleted = TRUE;
2722         }
2723       
2724       if (got_service_deleted)
2725         {
2726           /* The service started up and got a base address, but then
2727            * failed to register under EXISTENT_SERVICE_NAME
2728            */
2729           CheckServiceDeletedData csdd;
2730           
2731           csdd.expected_service_name = base_service;
2732           csdd.failed = FALSE;
2733           bus_test_clients_foreach (check_service_deleted_foreach,
2734                                     &csdd);
2735
2736           if (csdd.failed)
2737             goto out;
2738           
2739           /* Now we should get an error about the service exiting
2740            * if we didn't get it before.
2741            */
2742           if (!got_error)
2743             {
2744               block_connection_until_message_from_bus (context, connection);
2745               
2746               /* and process everything again */
2747               bus_test_run_everything (context);
2748
2749               if (!check_got_error (context, connection,
2750                                     DBUS_ERROR_SPAWN_CHILD_EXITED,
2751                                     NULL))
2752                 goto out;
2753             }
2754         }
2755       else
2756         {
2757           message = pop_message_waiting_for_memory (connection);
2758           if (message == NULL)
2759             {
2760               _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
2761               goto out;
2762             }
2763
2764           /* Check that ServiceCreated was correctly received */
2765           if (!check_service_auto_activated (context, connection, EXISTENT_SERVICE_NAME,
2766                                              base_service, message))
2767             goto out;
2768
2769           dbus_message_unref (message);
2770           message = NULL;
2771         }
2772
2773       /* Note: if this test is run in OOM mode, it will block when the bus
2774        * doesn't send a reply due to OOM.
2775        */
2776       block_connection_until_message_from_bus (context, connection);
2777       
2778       message = pop_message_waiting_for_memory (connection);
2779       if (message == NULL)
2780         {
2781           _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
2782           goto out;
2783         }
2784
2785       if (dbus_message_get_reply_serial (message) != serial)
2786         {
2787           _dbus_warn ("Wrong reply serial\n");
2788           goto out;
2789         }
2790
2791       dbus_message_unref (message);
2792       message = NULL;
2793       
2794       if (!check_send_exit_to_service (context, connection,
2795                                        EXISTENT_SERVICE_NAME,
2796                                        base_service))
2797         goto out;
2798     }
2799   
2800   retval = TRUE;
2801
2802  out:
2803   if (message)
2804     dbus_message_unref (message);
2805
2806   if (base_service)
2807     dbus_free (base_service);
2808
2809   return retval;
2810 }
2811
2812 typedef struct
2813 {
2814   Check1Func func;
2815   BusContext *context;
2816 } Check1Data;
2817
2818 static dbus_bool_t
2819 check_oom_check1_func (void *data)
2820 {
2821   Check1Data *d = data;
2822
2823   if (! (* d->func) (d->context))
2824     return FALSE;
2825   
2826   if (!check_no_leftovers (d->context))
2827     {
2828       _dbus_warn ("Messages were left over, should be covered by test suite\n");
2829       return FALSE;
2830     }
2831
2832   return TRUE;
2833 }
2834
2835 static void
2836 check1_try_iterations (BusContext *context,
2837                        const char *description,
2838                        Check1Func  func)
2839 {
2840   Check1Data d;
2841
2842   d.func = func;
2843   d.context = context;
2844
2845   if (!_dbus_test_oom_handling (description, check_oom_check1_func,
2846                                 &d))
2847     _dbus_assert_not_reached ("test failed");
2848 }
2849
2850 typedef struct
2851 {
2852   Check2Func func;
2853   BusContext *context;
2854   DBusConnection *connection;
2855 } Check2Data;
2856
2857 static dbus_bool_t
2858 check_oom_check2_func (void *data)
2859 {
2860   Check2Data *d = data;
2861
2862   if (! (* d->func) (d->context, d->connection))
2863     return FALSE;
2864   
2865   if (!check_no_leftovers (d->context))
2866     {
2867       _dbus_warn ("Messages were left over, should be covered by test suite");
2868       return FALSE;
2869     }
2870
2871   return TRUE;
2872 }
2873
2874 static void
2875 check2_try_iterations (BusContext     *context,
2876                        DBusConnection *connection,
2877                        const char     *description,
2878                        Check2Func      func)
2879 {
2880   Check2Data d;
2881
2882   d.func = func;
2883   d.context = context;
2884   d.connection = connection;
2885   
2886   if (!_dbus_test_oom_handling (description, check_oom_check2_func,
2887                                 &d))
2888     {
2889       _dbus_warn ("%s failed during oom\n", description);
2890       _dbus_assert_not_reached ("test failed");
2891     }
2892 }
2893
2894 dbus_bool_t
2895 bus_dispatch_test (const DBusString *test_data_dir)
2896 {
2897   BusContext *context;
2898   DBusConnection *foo;
2899   DBusConnection *bar;
2900   DBusConnection *baz;
2901   DBusError error;
2902
2903   dbus_error_init (&error);
2904   
2905   context = bus_context_new_test (test_data_dir,
2906                                   "valid-config-files/debug-allow-all.conf");
2907   if (context == NULL)
2908     return FALSE;
2909   
2910   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
2911   if (foo == NULL)
2912     _dbus_assert_not_reached ("could not alloc connection");
2913
2914   if (!bus_setup_debug_client (foo))
2915     _dbus_assert_not_reached ("could not set up connection");
2916
2917   if (!check_hello_message (context, foo))
2918     _dbus_assert_not_reached ("hello message failed");
2919
2920   if (!check_add_match_all (context, foo))
2921     _dbus_assert_not_reached ("AddMatch message failed");
2922   
2923   bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
2924   if (bar == NULL)
2925     _dbus_assert_not_reached ("could not alloc connection");
2926
2927   if (!bus_setup_debug_client (bar))
2928     _dbus_assert_not_reached ("could not set up connection");
2929
2930   if (!check_hello_message (context, bar))
2931     _dbus_assert_not_reached ("hello message failed");
2932
2933   if (!check_add_match_all (context, bar))
2934     _dbus_assert_not_reached ("AddMatch message failed");
2935   
2936   baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
2937   if (baz == NULL)
2938     _dbus_assert_not_reached ("could not alloc connection");
2939
2940   if (!bus_setup_debug_client (baz))
2941     _dbus_assert_not_reached ("could not set up connection");
2942
2943   if (!check_hello_message (context, baz))
2944     _dbus_assert_not_reached ("hello message failed");
2945
2946   if (!check_add_match_all (context, baz))
2947     _dbus_assert_not_reached ("AddMatch message failed");
2948
2949   if (!check_get_connection_unix_user (context, baz))
2950     _dbus_assert_not_reached ("GetConnectionUnixUser message failed");
2951
2952   if (!check_get_connection_unix_process_id (context, baz))
2953     _dbus_assert_not_reached ("GetConnectionUnixProcessID message failed");
2954   
2955   if (!check_no_leftovers (context))
2956     {
2957       _dbus_warn ("Messages were left over after setting up initial connections");
2958       _dbus_assert_not_reached ("initial connection setup failed");
2959     }
2960   
2961   check1_try_iterations (context, "create_and_hello",
2962                          check_hello_connection);
2963   
2964   check2_try_iterations (context, foo, "nonexistent_service_activation",
2965                          check_nonexistent_service_activation);
2966
2967   check2_try_iterations (context, foo, "segfault_service_activation",
2968                          check_segfault_service_activation);
2969   
2970   check2_try_iterations (context, foo, "existent_service_activation",
2971                          check_existent_service_activation);
2972   
2973   check2_try_iterations (context, foo, "nonexistent_service_auto_activation",
2974                          check_nonexistent_service_auto_activation);
2975   
2976   check2_try_iterations (context, foo, "segfault_service_auto_activation",
2977                          check_segfault_service_auto_activation);
2978
2979 #if 0
2980   /* Note: need to resolve some issues with the testing code in order to run
2981    * this in oom (handle that we sometimes don't get replies back from the bus
2982    * when oom happens, without blocking the test).
2983    */
2984   check2_try_iterations (context, foo, "existent_service_auto_activation",
2985                          check_existent_service_auto_activation);
2986 #endif
2987   
2988   if (!check_existent_service_auto_activation (context, foo))
2989     _dbus_assert_not_reached ("existent service auto activation failed");
2990
2991   _dbus_verbose ("Disconnecting foo, bar, and baz\n");
2992
2993   kill_client_connection_unchecked (foo);
2994   kill_client_connection_unchecked (bar);
2995   kill_client_connection_unchecked (baz);
2996
2997   bus_context_unref (context);
2998   
2999   return TRUE;
3000 }
3001
3002 dbus_bool_t
3003 bus_dispatch_sha1_test (const DBusString *test_data_dir)
3004 {
3005   BusContext *context;
3006   DBusConnection *foo;
3007   DBusError error;
3008
3009   dbus_error_init (&error);
3010   
3011   /* Test SHA1 authentication */
3012   _dbus_verbose ("Testing SHA1 context\n");
3013   
3014   context = bus_context_new_test (test_data_dir,
3015                                   "valid-config-files/debug-allow-all-sha1.conf");
3016   if (context == NULL)
3017     return FALSE;
3018
3019   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
3020   if (foo == NULL)
3021     _dbus_assert_not_reached ("could not alloc connection");
3022
3023   if (!bus_setup_debug_client (foo))
3024     _dbus_assert_not_reached ("could not set up connection");
3025
3026   if (!check_hello_message (context, foo))
3027     _dbus_assert_not_reached ("hello message failed");
3028
3029   if (!check_add_match_all (context, foo))
3030     _dbus_assert_not_reached ("addmatch message failed");
3031   
3032   if (!check_no_leftovers (context))
3033     {
3034       _dbus_warn ("Messages were left over after setting up initial SHA-1 connection\n");
3035       _dbus_assert_not_reached ("initial connection setup failed");
3036     }
3037   
3038   check1_try_iterations (context, "create_and_hello_sha1",
3039                          check_hello_connection);
3040
3041   kill_client_connection_unchecked (foo);
3042
3043   bus_context_unref (context);
3044
3045   return TRUE;
3046 }
3047
3048 #endif /* DBUS_BUILD_TESTS */