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