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