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