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