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