-/* -*- mode: C; c-file-style: "gnu" -*- */
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* dispatch.c Message dispatcher
*
* Copyright (C) 2003 CodeFactory AB
- * Copyright (C) 2003 Red Hat, Inc.
+ * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ * Copyright (C) 2004 Imendio HB
+ *
+ * Licensed under the Academic Free License version 2.1
*
- * Licensed under the Academic Free License version 1.2
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
+#include <config.h>
#include "dispatch.h"
#include "connection.h"
#include "driver.h"
#include "services.h"
+#include "activation.h"
#include "utils.h"
#include "bus.h"
#include "signals.h"
#include <dbus/dbus-internals.h>
#include <string.h>
+#ifdef HAVE_UNIX_FD_PASSING
+#include <dbus/dbus-sysdeps-unix.h>
+#include <unistd.h>
+#endif
+
+#ifndef TEST_CONNECTION
+/*
+ TODO autotools:
+ move to build system as already done for cmake
+*/
+#ifdef DBUS_UNIX
+#define TEST_CONNECTION "debug-pipe:name=test-server"
+#else
+#define TEST_CONNECTION "tcp:host=localhost,port=1234"
+#endif
+#endif
+
static dbus_bool_t
send_one_message (DBusConnection *connection,
BusContext *context,
BusTransaction *transaction,
DBusError *error)
{
- if (!bus_context_check_security_policy (context,
+ if (!bus_context_check_security_policy (context, transaction,
sender,
addressed_recipient,
connection,
message,
NULL))
return TRUE; /* silently don't send it */
-
+
+ if (dbus_message_contains_unix_fds(message) &&
+ !dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD))
+ return TRUE; /* silently don't send it */
+
if (!bus_transaction_send (transaction,
connection,
message))
_dbus_assert (sender == NULL || bus_connection_is_active (sender));
_dbus_assert (dbus_message_get_sender (message) != NULL);
+ context = bus_transaction_get_context (transaction);
+
+ /* First, send the message to the addressed_recipient, if there is one. */
+ if (addressed_recipient != NULL)
+ {
+ if (!bus_context_check_security_policy (context, transaction,
+ sender, addressed_recipient,
+ addressed_recipient,
+ message, error))
+ return FALSE;
+
+ if (dbus_message_contains_unix_fds (message) &&
+ !dbus_connection_can_send_type (addressed_recipient,
+ DBUS_TYPE_UNIX_FD))
+ {
+ dbus_set_error (error,
+ DBUS_ERROR_NOT_SUPPORTED,
+ "Tried to send message with Unix file descriptors"
+ "to a client that doesn't support that.");
+ return FALSE;
+ }
+
+ /* Dispatch the message */
+ if (!bus_transaction_send (transaction, addressed_recipient, message))
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ }
+
+ /* Now dispatch to others who look interested in this message */
connections = bus_transaction_get_connections (transaction);
-
dbus_error_init (&tmp_error);
- context = bus_transaction_get_context (transaction);
matchmaker = bus_context_get_matchmaker (context);
recipients = NULL;
- if (!bus_matchmaker_get_recipients (matchmaker,
- bus_context_get_connections (context),
+ if (!bus_matchmaker_get_recipients (matchmaker, connections,
sender, addressed_recipient, message,
&recipients))
{
}
_dbus_list_clear (&recipients);
-
+
if (dbus_error_is_set (&tmp_error))
{
dbus_move_error (&tmp_error, error);
BusContext *context;
DBusHandlerResult result;
DBusConnection *addressed_recipient;
-
+
result = DBUS_HANDLER_RESULT_HANDLED;
-
+
transaction = NULL;
addressed_recipient = NULL;
dbus_error_init (&error);
-
+
context = bus_connection_get_context (connection);
_dbus_assert (context != NULL);
-
+
/* If we can't even allocate an OOM error, we just go to sleep
* until we can.
*/
while (!bus_connection_preallocate_oom_error (connection))
_dbus_wait_for_memory ();
-
+
/* Ref connection in case we disconnect it at some point in here */
dbus_connection_ref (connection);
-
+
service_name = dbus_message_get_destination (message);
#ifdef DBUS_ENABLE_VERBOSE_MODE
interface_name = dbus_message_get_interface (message);
member_name = dbus_message_get_member (message);
error_name = dbus_message_get_error_name (message);
-
+
_dbus_verbose ("DISPATCH: %s %s %s to %s\n",
interface_name ? interface_name : "(no interface)",
member_name ? member_name : "(no member)",
service_name ? service_name : "peer");
}
#endif /* DBUS_ENABLE_VERBOSE_MODE */
-
+
/* If service_name is NULL, if it's a signal we send it to all
- * connections with a match rule. If it's not a signal, it goes to
- * the bus daemon but doesn't go "on the bus"; e.g. a peer-to-peer
- * ping. Handle these immediately, especially disconnection
- * messages. There are no security policy checks on these.
+ * connections with a match rule. If it's not a signal, there
+ * are some special cases here but mostly we just bail out.
*/
if (service_name == NULL)
{
if (dbus_message_is_signal (message,
- DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
+ DBUS_INTERFACE_LOCAL,
"Disconnected"))
{
bus_connection_disconnected (connection);
goto out;
}
}
-
+
/* Create our transaction */
transaction = bus_transaction_new (context);
if (transaction == NULL)
BUS_SET_OOM (&error);
goto out;
}
-
+
/* Assign a sender to the message */
if (bus_connection_is_active (connection))
{
*/
service_name = dbus_message_get_destination (message);
}
-
+
if (service_name &&
- strcmp (service_name, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0) /* to bus driver */
+ strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
{
- if (!bus_context_check_security_policy (context,
+ if (!bus_context_check_security_policy (context, transaction,
connection, NULL, NULL, message, &error))
{
_dbus_verbose ("Security policy rejected message\n");
goto out;
}
- _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
+ _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS);
if (!bus_driver_handle_message (connection, transaction, message, &error))
goto out;
}
else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
{
_dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
- dbus_connection_disconnect (connection);
+ dbus_connection_close (connection);
goto out;
}
else if (service_name != NULL) /* route to named service */
BusRegistry *registry;
_dbus_assert (service_name != NULL);
-
+
registry = bus_connection_get_registry (connection);
-
+
_dbus_string_init_const (&service_string, service_name);
service = bus_registry_lookup (registry, &service_string);
- if (service == NULL)
+ if (service == NULL && dbus_message_get_auto_start (message))
+ {
+ BusActivation *activation;
+ /* We can't do the security policy check here, since the addressed
+ * recipient service doesn't exist yet. We do it before sending the
+ * message after the service has been created.
+ */
+ activation = bus_connection_get_activation (connection);
+
+ if (!bus_activation_activate_service (activation, connection, transaction, TRUE,
+ message, service_name, &error))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (&error);
+ _dbus_verbose ("bus_activation_activate_service() failed: %s\n", error.name);
+ goto out;
+ }
+
+ goto out;
+ }
+ else if (service == NULL)
{
dbus_set_error (&error,
- DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
- "Service \"%s\" does not exist",
+ DBUS_ERROR_NAME_HAS_NO_OWNER,
+ "Name \"%s\" does not exist",
service_name);
goto out;
}
else
- {
- addressed_recipient = bus_service_get_primary_owner (service);
+ {
+ addressed_recipient = bus_service_get_primary_owners_connection (service);
_dbus_assert (addressed_recipient != NULL);
-
- if (!bus_context_check_security_policy (context,
- connection, addressed_recipient,
- addressed_recipient,
- message, &error))
- goto out;
-
- /* Dispatch the message */
- if (!bus_transaction_send (transaction, addressed_recipient, message))
- {
- BUS_SET_OOM (&error);
- goto out;
- }
}
}
- /* Now match the messages against any match rules, which will send
- * out signals and such. addressed_recipient may == NULL.
+ /* Now send the message to its destination (or not, if
+ * addressed_recipient == NULL), and match it against other connections'
+ * match rules.
*/
if (!bus_dispatch_matches (transaction, connection, addressed_recipient, message, &error))
goto out;
-
+
out:
if (dbus_error_is_set (&error))
{
* the OOM error
*/
_dbus_assert (transaction != NULL);
-
if (!bus_transaction_send_error_reply (transaction, connection,
&error, message))
{
bus_connection_send_oom_error (connection, message);
-
+
/* cancel transaction due to OOM */
if (transaction != NULL)
{
}
}
}
-
+
+
dbus_error_free (&error);
}
dbus_bool_t
bus_dispatch_add_connection (DBusConnection *connection)
-{
+{
if (!dbus_connection_add_filter (connection,
bus_dispatch_message_filter,
NULL, NULL))
return FALSE;
-
+
return TRUE;
}
#ifdef DBUS_BUILD_TESTS
+#include <stdio.h>
+
+/* This is used to know whether we need to block in order to finish
+ * sending a message, or whether the initial dbus_connection_send()
+ * already flushed the queue.
+ */
+#define SEND_PENDING(connection) (dbus_connection_has_messages_to_send (connection))
+
typedef dbus_bool_t (* Check1Func) (BusContext *context);
typedef dbus_bool_t (* Check2Func) (BusContext *context,
DBusConnection *connection);
static void
block_connection_until_message_from_bus (BusContext *context,
- DBusConnection *connection)
+ DBusConnection *connection,
+ const char *what_is_expected)
{
+ _dbus_verbose ("expecting: %s\n", what_is_expected);
+
while (dbus_connection_get_dispatch_status (connection) ==
DBUS_DISPATCH_COMPLETE &&
dbus_connection_get_is_connected (connection))
}
}
+static void
+spin_connection_until_authenticated (BusContext *context,
+ DBusConnection *connection)
+{
+ _dbus_verbose ("Spinning to auth connection %p\n", connection);
+ while (!dbus_connection_get_is_authenticated (connection) &&
+ dbus_connection_get_is_connected (connection))
+ {
+ bus_test_run_bus_loop (context, FALSE);
+ bus_test_run_clients_loop (FALSE);
+ }
+ _dbus_verbose (" ... done spinning to auth connection %p\n", connection);
+}
+
/* compensate for fact that pop_message() can return #NULL due to OOM */
static DBusMessage*
pop_message_waiting_for_memory (DBusConnection *connection)
return dbus_connection_pop_message (connection);
}
+static DBusMessage*
+borrow_message_waiting_for_memory (DBusConnection *connection)
+{
+ while (dbus_connection_get_dispatch_status (connection) ==
+ DBUS_DISPATCH_NEED_MEMORY)
+ _dbus_wait_for_memory ();
+
+ return dbus_connection_borrow_message (connection);
+}
+
static void
warn_unexpected_real (DBusConnection *connection,
DBusMessage *message,
const char *function,
int line)
{
- _dbus_warn ("%s:%d received message interface \"%s\" member \"%s\" error name \"%s\" on %p, expecting %s\n",
- function, line,
- dbus_message_get_interface (message) ?
- dbus_message_get_interface (message) : "(unset)",
- dbus_message_get_member (message) ?
- dbus_message_get_member (message) : "(unset)",
- dbus_message_get_error_name (message) ?
- dbus_message_get_error_name (message) : "(unset)",
- connection,
- expected);
+ if (message)
+ _dbus_warn ("%s:%d received message interface \"%s\" member \"%s\" error name \"%s\" on %p, expecting %s\n",
+ function, line,
+ dbus_message_get_interface (message) ?
+ dbus_message_get_interface (message) : "(unset)",
+ dbus_message_get_member (message) ?
+ dbus_message_get_member (message) : "(unset)",
+ dbus_message_get_error_name (message) ?
+ dbus_message_get_error_name (message) : "(unset)",
+ connection,
+ expected);
+ else
+ _dbus_warn ("%s:%d received no message on %p, expecting %s\n",
+ function, line, connection, expected);
}
#define warn_unexpected(connection, message, expected) \
connection);
}
+typedef enum
+{
+ SERVICE_CREATED,
+ OWNER_CHANGED,
+ SERVICE_DELETED
+} ServiceInfoKind;
+
typedef struct
{
+ ServiceInfoKind expected_kind;
const char *expected_service_name;
dbus_bool_t failed;
-} CheckServiceDeletedData;
+ DBusConnection *skip_connection;
+} CheckServiceOwnerChangedData;
static dbus_bool_t
-check_service_deleted_foreach (DBusConnection *connection,
- void *data)
+check_service_owner_changed_foreach (DBusConnection *connection,
+ void *data)
{
- CheckServiceDeletedData *d = data;
+ CheckServiceOwnerChangedData *d = data;
DBusMessage *message;
DBusError error;
- char *service_name;
+ const char *service_name, *old_owner, *new_owner;
+
+ if (d->expected_kind == SERVICE_CREATED
+ && connection == d->skip_connection)
+ return TRUE;
dbus_error_init (&error);
d->failed = TRUE;
- service_name = NULL;
-
+
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
_dbus_warn ("Did not receive a message on %p, expecting %s\n",
- connection, "ServiceDeleted");
+ connection, "NameOwnerChanged");
goto out;
}
else if (!dbus_message_is_signal (message,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
- "ServiceDeleted"))
+ DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged"))
{
- warn_unexpected (connection, message, "ServiceDeleted");
+ warn_unexpected (connection, message, "NameOwnerChanged");
goto out;
}
else
{
- if (!dbus_message_get_args (message, &error,
- DBUS_TYPE_STRING, &service_name,
- DBUS_TYPE_INVALID))
+ reget_service_info_data:
+ service_name = NULL;
+ old_owner = NULL;
+ new_owner = NULL;
+
+ dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &service_name,
+ DBUS_TYPE_STRING, &old_owner,
+ DBUS_TYPE_STRING, &new_owner,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_error_is_set (&error))
{
if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
{
- _dbus_verbose ("no memory to get service name arg\n");
+ dbus_error_free (&error);
+ _dbus_wait_for_memory ();
+ goto reget_service_info_data;
}
else
{
- _dbus_assert (dbus_error_is_set (&error));
- _dbus_warn ("Did not get the expected single string argument\n");
+ _dbus_warn ("Did not get the expected arguments\n");
goto out;
}
}
- else if (strcmp (service_name, d->expected_service_name) != 0)
+
+ if ((d->expected_kind == SERVICE_CREATED && ( old_owner[0] || !new_owner[0]))
+ || (d->expected_kind == OWNER_CHANGED && (!old_owner[0] || !new_owner[0]))
+ || (d->expected_kind == SERVICE_DELETED && (!old_owner[0] || new_owner[0])))
+ {
+ _dbus_warn ("inconsistent NameOwnerChanged arguments\n");
+ goto out;
+ }
+
+ if (strcmp (service_name, d->expected_service_name) != 0)
{
- _dbus_warn ("expected deletion of service %s, got deletion of %s\n",
+ _dbus_warn ("expected info on service %s, got info on %s\n",
d->expected_service_name,
service_name);
goto out;
}
+
+ if (*service_name == ':' && new_owner[0]
+ && strcmp (service_name, new_owner) != 0)
+ {
+ _dbus_warn ("inconsistent ServiceOwnedChanged message (\"%s\" [ %s -> %s ])\n",
+ service_name, old_owner, new_owner);
+ goto out;
+ }
}
d->failed = FALSE;
-
+
out:
- dbus_free (service_name);
dbus_error_free (&error);
-
+
if (message)
dbus_message_unref (message);
return !d->failed;
}
+
static void
kill_client_connection (BusContext *context,
DBusConnection *connection)
{
char *base_service;
const char *s;
- CheckServiceDeletedData csdd;
+ CheckServiceOwnerChangedData socd;
_dbus_verbose ("killing connection %p\n", connection);
-
- s = dbus_bus_get_base_service (connection);
+
+ s = dbus_bus_get_unique_name (connection);
_dbus_assert (s != NULL);
while ((base_service = _dbus_strdup (s)) == NULL)
_dbus_wait_for_memory ();
dbus_connection_ref (connection);
-
+
/* kick in the disconnect handler that unrefs the connection */
- dbus_connection_disconnect (connection);
+ dbus_connection_close (connection);
bus_test_run_everything (context);
-
+
_dbus_assert (bus_test_client_listed (connection));
-
+
/* Run disconnect handler in test.c */
if (bus_connection_dispatch_one_message (connection))
_dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
-
+
_dbus_assert (!dbus_connection_get_is_connected (connection));
dbus_connection_unref (connection);
connection = NULL;
_dbus_assert (!bus_test_client_listed (connection));
-
- csdd.expected_service_name = base_service;
- csdd.failed = FALSE;
- bus_test_clients_foreach (check_service_deleted_foreach,
- &csdd);
+ socd.expected_kind = SERVICE_DELETED;
+ socd.expected_service_name = base_service;
+ socd.failed = FALSE;
+ socd.skip_connection = NULL;
+
+ bus_test_clients_foreach (check_service_owner_changed_foreach,
+ &socd);
dbus_free (base_service);
-
- if (csdd.failed)
- _dbus_assert_not_reached ("didn't get the expected ServiceDeleted messages");
-
+
+ if (socd.failed)
+ _dbus_assert_not_reached ("didn't get the expected NameOwnerChanged (deletion) messages");
+
if (!check_no_leftovers (context))
_dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
}
{
/* This kills the connection without expecting it to affect
* the rest of the bus.
- */
+ */
_dbus_verbose ("Unchecked kill of connection %p\n", connection);
dbus_connection_ref (connection);
- dbus_connection_disconnect (connection);
+ dbus_connection_close (connection);
/* dispatching disconnect handler will unref once */
if (bus_connection_dispatch_one_message (connection))
_dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
return !d->failed;
}
-typedef struct
-{
- DBusConnection *skip_connection;
- const char *expected_service_name;
- dbus_bool_t failed;
-} CheckServiceCreatedData;
-
-static dbus_bool_t
-check_service_created_foreach (DBusConnection *connection,
- void *data)
-{
- CheckServiceCreatedData *d = data;
- DBusMessage *message;
- DBusError error;
- char *service_name;
-
- if (connection == d->skip_connection)
- return TRUE;
-
- dbus_error_init (&error);
- d->failed = TRUE;
- service_name = NULL;
-
- message = pop_message_waiting_for_memory (connection);
- if (message == NULL)
- {
- _dbus_warn ("Did not receive a message on %p, expecting %s\n",
- connection, "ServiceCreated");
- goto out;
- }
- else if (!dbus_message_is_signal (message,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
- "ServiceCreated"))
- {
- warn_unexpected (connection, message, "ServiceCreated");
- goto out;
- }
- else
- {
- if (!dbus_message_get_args (message, &error,
- DBUS_TYPE_STRING, &service_name,
- DBUS_TYPE_INVALID))
- {
- if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
- {
- _dbus_verbose ("no memory to get service name arg\n");
- }
- else
- {
- _dbus_assert (dbus_error_is_set (&error));
- _dbus_warn ("Did not get the expected single string argument\n");
- goto out;
- }
- }
- else if (strcmp (service_name, d->expected_service_name) != 0)
- {
- _dbus_warn ("expected creation of service %s, got creation of %s\n",
- d->expected_service_name,
- service_name);
- goto out;
- }
- }
-
- d->failed = FALSE;
-
- out:
- dbus_free (service_name);
- dbus_error_free (&error);
-
- if (message)
- dbus_message_unref (message);
-
- return !d->failed;
-}
-
static dbus_bool_t
check_no_leftovers (BusContext *context)
{
nmd.failed = FALSE;
bus_test_clients_foreach (check_no_messages_foreach,
&nmd);
-
+
if (nmd.failed)
- return FALSE;
+ {
+ _dbus_verbose ("leftover message found\n");
+ return FALSE;
+ }
else
return TRUE;
}
DBusConnection *connection)
{
DBusMessage *message;
+ DBusMessage *name_message;
dbus_uint32_t serial;
dbus_bool_t retval;
DBusError error;
- char *name;
- char *acquired;
+ const char *name;
+ const char *acquired;
retval = FALSE;
dbus_error_init (&error);
name = NULL;
acquired = NULL;
message = NULL;
+ name_message = NULL;
_dbus_verbose ("check_hello_message for %p\n", connection);
-
- message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
- DBUS_PATH_ORG_FREEDESKTOP_DBUS,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
"Hello");
if (message == NULL)
return TRUE;
+ dbus_connection_ref (connection); /* because we may get disconnected */
+
if (!dbus_connection_send (connection, message, &serial))
{
dbus_message_unref (message);
+ dbus_connection_unref (connection);
return TRUE;
}
+ _dbus_assert (dbus_message_has_signature (message, ""));
+
dbus_message_unref (message);
message = NULL;
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
+
+ dbus_connection_unref (connection);
+
+ return TRUE;
+ }
+
/* send our message */
- bus_test_run_clients_loop (TRUE);
+ bus_test_run_clients_loop (SEND_PENDING (connection));
- dbus_connection_ref (connection); /* because we may get disconnected */
- block_connection_until_message_from_bus (context, connection);
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
+
+ dbus_connection_unref (connection);
+
+ return TRUE;
+ }
+
+ block_connection_until_message_from_bus (context, connection, "reply to Hello");
if (!dbus_connection_get_is_connected (connection))
{
- _dbus_verbose ("connection was disconnected\n");
-
+ _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
+
dbus_connection_unref (connection);
-
+
return TRUE;
}
dbus_connection_unref (connection);
-
+
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
verbose_message_received (connection, message);
- if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
_dbus_warn ("Message has wrong sender %s\n",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
}
-
+
if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
{
if (dbus_message_is_error (message,
}
else
{
- CheckServiceCreatedData scd;
-
+ CheckServiceOwnerChangedData socd;
+
if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
{
; /* good, expected */
_dbus_verbose ("Got hello name: %s\n", name);
- while (!dbus_bus_set_base_service (connection, name))
+ while (!dbus_bus_set_unique_name (connection, name))
_dbus_wait_for_memory ();
-
- scd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
- scd.failed = FALSE;
- scd.expected_service_name = name;
- bus_test_clients_foreach (check_service_created_foreach,
- &scd);
-
- if (scd.failed)
+
+ socd.expected_kind = SERVICE_CREATED;
+ socd.expected_service_name = name;
+ socd.failed = FALSE;
+ socd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
+ bus_test_clients_foreach (check_service_owner_changed_foreach,
+ &socd);
+
+ if (socd.failed)
goto out;
-
+
+ name_message = message;
/* Client should also have gotten ServiceAcquired */
- dbus_message_unref (message);
+
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
_dbus_warn ("Expecting %s, got nothing\n",
- "ServiceAcquired");
+ "NameAcquired");
goto out;
}
-
+ if (! dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
+ "NameAcquired"))
+ {
+ _dbus_warn ("Expecting %s, got smthg else\n",
+ "NameAcquired");
+ goto out;
+ }
+
retry_get_acquired_name:
if (!dbus_message_get_args (message, &error,
DBUS_TYPE_STRING, &acquired,
acquired, name);
goto out;
}
+ acquired = NULL;
}
if (!check_no_leftovers (context))
goto out;
-
+
retval = TRUE;
-
+
out:
+ _dbus_verbose ("ending - retval = %d\n", retval);
+
dbus_error_free (&error);
-
- dbus_free (name);
- dbus_free (acquired);
-
+
if (message)
dbus_message_unref (message);
-
+
+ if (name_message)
+ dbus_message_unref (name_message);
+
return retval;
}
* but the correct thing may include OOM errors.
*/
static dbus_bool_t
-check_add_match_all (BusContext *context,
- DBusConnection *connection)
+check_double_hello_message (BusContext *context,
+ DBusConnection *connection)
{
DBusMessage *message;
- dbus_bool_t retval;
dbus_uint32_t serial;
+ dbus_bool_t retval;
DBusError error;
retval = FALSE;
dbus_error_init (&error);
message = NULL;
- _dbus_verbose ("check_add_match_all for %p\n", connection);
-
- message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
- DBUS_PATH_ORG_FREEDESKTOP_DBUS,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
- "AddMatch");
+ _dbus_verbose ("check_double_hello_message for %p\n", connection);
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "Hello");
if (message == NULL)
return TRUE;
- /* empty string match rule matches everything */
- if (!dbus_message_append_args (message, DBUS_TYPE_STRING, "",
- DBUS_TYPE_INVALID))
- {
- dbus_message_unref (message);
- return TRUE;
- }
-
if (!dbus_connection_send (connection, message, &serial))
{
dbus_message_unref (message);
message = NULL;
/* send our message */
- bus_test_run_clients_loop (TRUE);
+ bus_test_run_clients_loop (SEND_PENDING (connection));
dbus_connection_ref (connection); /* because we may get disconnected */
- block_connection_until_message_from_bus (context, connection);
+ block_connection_until_message_from_bus (context, connection, "reply to Hello");
if (!dbus_connection_get_is_connected (connection))
{
_dbus_verbose ("connection was disconnected\n");
-
+
dbus_connection_unref (connection);
-
+
return TRUE;
}
dbus_connection_unref (connection);
-
+
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
_dbus_warn ("Did not receive a reply to %s %d on %p\n",
- "AddMatch", serial, connection);
+ "Hello", serial, connection);
goto out;
}
verbose_message_received (connection, message);
- if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
_dbus_warn ("Message has wrong sender %s\n",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
}
-
- if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
- {
- if (dbus_message_is_error (message,
- DBUS_ERROR_NO_MEMORY))
- {
- ; /* good, this is a valid response */
- }
- else
- {
- warn_unexpected (connection, message, "not this error");
- goto out;
- }
- }
- else
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
{
- if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
- {
- ; /* good, expected */
- _dbus_assert (dbus_message_get_reply_serial (message) == serial);
- }
- else
- {
- warn_unexpected (connection, message, "method return for AddMatch");
-
- goto out;
- }
+ warn_unexpected (connection, message, "method return for Hello");
+ goto out;
}
if (!check_no_leftovers (context))
goto out;
-
+
retval = TRUE;
-
+
out:
dbus_error_free (&error);
-
+
if (message)
dbus_message_unref (message);
-
+
return retval;
}
* but the correct thing may include OOM errors.
*/
static dbus_bool_t
-check_hello_connection (BusContext *context)
+check_get_connection_unix_user (BusContext *context,
+ DBusConnection *connection)
{
- DBusConnection *connection;
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
DBusError error;
+ const char *base_service_name;
+ dbus_uint32_t uid;
+ retval = FALSE;
dbus_error_init (&error);
+ message = NULL;
- connection = dbus_connection_open ("debug-pipe:name=test-server", &error);
- if (connection == NULL)
+ _dbus_verbose ("check_get_connection_unix_user for %p\n", connection);
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "GetConnectionUnixUser");
+
+ if (message == NULL)
+ return TRUE;
+
+ base_service_name = dbus_bus_get_unique_name (connection);
+
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &base_service_name,
+ DBUS_TYPE_INVALID))
{
- _DBUS_ASSERT_ERROR_IS_SET (&error);
- dbus_error_free (&error);
+ dbus_message_unref (message);
return TRUE;
}
- if (!bus_setup_debug_client (connection))
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ /* send our message */
+ bus_test_run_clients_loop (SEND_PENDING (connection));
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ dbus_connection_ref (connection); /* because we may get disconnected */
+ block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixUser");
+
+ if (!dbus_connection_get_is_connected (connection))
{
- dbus_connection_disconnect (connection);
+ _dbus_verbose ("connection was disconnected\n");
+
dbus_connection_unref (connection);
+
return TRUE;
}
- if (!check_hello_message (context, connection))
- return FALSE;
-
- if (dbus_bus_get_base_service (connection) == NULL)
+ dbus_connection_unref (connection);
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
{
- /* We didn't successfully register, so we can't
- * do the usual kill_client_connection() checks
- */
- kill_client_connection_unchecked (connection);
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "GetConnectionUnixUser", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+
+ goto out;
+ }
}
else
{
- if (!check_add_match_all (context, connection))
- return FALSE;
-
- kill_client_connection (context, connection);
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ {
+ ; /* good, expected */
+ }
+ else
+ {
+ warn_unexpected (connection, message,
+ "method_return for GetConnectionUnixUser");
+
+ goto out;
+ }
+
+ retry_get_property:
+
+ if (!dbus_message_get_args (message, &error,
+ DBUS_TYPE_UINT32, &uid,
+ DBUS_TYPE_INVALID))
+ {
+ if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ {
+ _dbus_verbose ("no memory to get uid by GetConnectionUnixUser\n");
+ dbus_error_free (&error);
+ _dbus_wait_for_memory ();
+ goto retry_get_property;
+ }
+ else
+ {
+ _dbus_assert (dbus_error_is_set (&error));
+ _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixUser\n");
+ goto out;
+ }
+ }
}
- return TRUE;
-}
+ if (!check_no_leftovers (context))
+ goto out;
-#define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
+ retval = TRUE;
+
+ out:
+ dbus_error_free (&error);
+
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
/* returns TRUE if the correct thing happens,
* but the correct thing may include OOM errors.
*/
static dbus_bool_t
-check_nonexistent_service_activation (BusContext *context,
+check_get_connection_unix_process_id (BusContext *context,
DBusConnection *connection)
{
DBusMessage *message;
dbus_uint32_t serial;
dbus_bool_t retval;
DBusError error;
-
+ const char *base_service_name;
+ dbus_uint32_t pid;
+
+ retval = FALSE;
dbus_error_init (&error);
-
- message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
- DBUS_PATH_ORG_FREEDESKTOP_DBUS,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
- "ActivateService");
+ message = NULL;
+
+ _dbus_verbose ("check_get_connection_unix_process_id for %p\n", connection);
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "GetConnectionUnixProcessID");
if (message == NULL)
return TRUE;
+ base_service_name = dbus_bus_get_unique_name (connection);
+
if (!dbus_message_append_args (message,
- DBUS_TYPE_STRING, NONEXISTENT_SERVICE_NAME,
- DBUS_TYPE_UINT32, 0,
+ DBUS_TYPE_STRING, &base_service_name,
DBUS_TYPE_INVALID))
{
dbus_message_unref (message);
return TRUE;
}
-
+
if (!dbus_connection_send (connection, message, &serial))
{
dbus_message_unref (message);
return TRUE;
}
+ /* send our message */
+ bus_test_run_clients_loop (SEND_PENDING (connection));
+
dbus_message_unref (message);
message = NULL;
- bus_test_run_everything (context);
- block_connection_until_message_from_bus (context, connection);
- bus_test_run_everything (context);
+ dbus_connection_ref (connection); /* because we may get disconnected */
+ block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixProcessID");
if (!dbus_connection_get_is_connected (connection))
{
_dbus_verbose ("connection was disconnected\n");
+
+ dbus_connection_unref (connection);
+
return TRUE;
}
-
- retval = FALSE;
-
+
+ dbus_connection_unref (connection);
+
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
_dbus_warn ("Did not receive a reply to %s %d on %p\n",
- "ActivateService", serial, connection);
+ "GetConnectionUnixProcessID", serial, connection);
goto out;
}
if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
{
- if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
- {
- _dbus_warn ("Message has wrong sender %s\n",
- dbus_message_get_sender (message) ?
- dbus_message_get_sender (message) : "(none)");
- goto out;
- }
-
- if (dbus_message_is_error (message,
- DBUS_ERROR_NO_MEMORY))
+ if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
{
; /* good, this is a valid response */
}
- else if (dbus_message_is_error (message,
- DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
+#ifdef DBUS_WIN
+ else if (dbus_message_is_error (message, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN))
{
- ; /* good, this is expected also */
+ /* We are expecting this error, since we know in the test suite we aren't
+ * talking to a client running on UNIX
+ */
+ _dbus_verbose ("Windows correctly does not support GetConnectionUnixProcessID\n");
}
+#endif
else
{
warn_unexpected (connection, message, "not this error");
+
goto out;
}
}
else
{
- _dbus_warn ("Did not expect to successfully activate %s\n",
- NONEXISTENT_SERVICE_NAME);
+#ifdef DBUS_WIN
+ warn_unexpected (connection, message, "GetConnectionUnixProcessID to fail on Windows");
goto out;
- }
-
- retval = TRUE;
-
- out:
- if (message)
- dbus_message_unref (message);
-
- return retval;
-}
-
-static dbus_bool_t
-check_base_service_activated (BusContext *context,
- DBusConnection *connection,
- DBusMessage *initial_message,
- char **base_service_p)
-{
- DBusMessage *message;
- dbus_bool_t retval;
- DBusError error;
- char *base_service;
-
- base_service = NULL;
- retval = FALSE;
-
- dbus_error_init (&error);
+#else
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ {
+ ; /* good, expected */
+ }
+ else
+ {
+ warn_unexpected (connection, message,
+ "method_return for GetConnectionUnixProcessID");
- message = initial_message;
- dbus_message_ref (message);
+ goto out;
+ }
- if (dbus_message_is_signal (message,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
- "ServiceCreated"))
- {
- char *service_name;
- CheckServiceCreatedData scd;
+ retry_get_property:
- reget_service_name_arg:
if (!dbus_message_get_args (message, &error,
- DBUS_TYPE_STRING, &service_name,
+ DBUS_TYPE_UINT32, &pid,
DBUS_TYPE_INVALID))
{
if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
{
+ _dbus_verbose ("no memory to get pid by GetConnectionUnixProcessID\n");
dbus_error_free (&error);
_dbus_wait_for_memory ();
- goto reget_service_name_arg;
+ goto retry_get_property;
}
else
{
- _dbus_warn ("Message %s doesn't have a service name: %s\n",
- "ServiceCreated",
- error.message);
- dbus_error_free (&error);
+ _dbus_assert (dbus_error_is_set (&error));
+ _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixProcessID\n");
goto out;
}
}
-
- if (*service_name != ':')
+ else
{
- _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
- service_name);
- goto out;
+ /* test if returned pid is the same as our own pid
+ *
+ * @todo It would probably be good to restructure the tests
+ * in a way so our parent is the bus that we're testing
+ * cause then we can test that the pid returned matches
+ * getppid()
+ */
+ if (pid != (dbus_uint32_t) _dbus_getpid ())
+ {
+ _dbus_assert (dbus_error_is_set (&error));
+ _dbus_warn ("Result from GetConnectionUnixProcessID is not our own pid\n");
+ goto out;
+ }
}
-
- base_service = service_name;
- service_name = NULL;
-
- scd.skip_connection = connection;
- scd.failed = FALSE;
- scd.expected_service_name = base_service;
- bus_test_clients_foreach (check_service_created_foreach,
- &scd);
-
- if (scd.failed)
- goto out;
+#endif /* !DBUS_WIN */
}
- else
- {
- warn_unexpected (connection, message, "ServiceCreated for base service");
- goto out;
- }
+ if (!check_no_leftovers (context))
+ goto out;
retval = TRUE;
- if (base_service_p)
- {
- *base_service_p = base_service;
- base_service = NULL;
- }
-
out:
+ dbus_error_free (&error);
+
if (message)
dbus_message_unref (message);
- if (base_service)
- dbus_free (base_service);
-
return retval;
}
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
static dbus_bool_t
-check_service_activated (BusContext *context,
- DBusConnection *connection,
- const char *activated_name,
- const char *base_service_name,
- DBusMessage *initial_message)
+check_add_match_all (BusContext *context,
+ DBusConnection *connection)
{
DBusMessage *message;
dbus_bool_t retval;
+ dbus_uint32_t serial;
DBusError error;
- dbus_uint32_t activation_result;
-
+ const char *empty = "";
+
retval = FALSE;
-
dbus_error_init (&error);
+ message = NULL;
- message = initial_message;
- dbus_message_ref (message);
+ _dbus_verbose ("check_add_match_all for %p\n", connection);
- if (dbus_message_is_signal (message,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
- "ServiceCreated"))
- {
- char *service_name;
- CheckServiceCreatedData scd;
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "AddMatch");
- reget_service_name_arg:
- if (!dbus_message_get_args (message, &error,
- DBUS_TYPE_STRING, &service_name,
- DBUS_TYPE_INVALID))
- {
- if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
- {
- dbus_error_free (&error);
- _dbus_wait_for_memory ();
- goto reget_service_name_arg;
- }
- else
- {
- _dbus_warn ("Message %s doesn't have a service name: %s\n",
- "ServiceCreated",
- error.message);
- dbus_error_free (&error);
- goto out;
- }
- }
+ if (message == NULL)
+ return TRUE;
- if (strcmp (service_name, activated_name) != 0)
- {
+ /* empty string match rule matches everything */
+ if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &empty,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ dbus_connection_ref (connection); /* because we may get disconnected */
+
+ /* send our message */
+ bus_test_run_clients_loop (SEND_PENDING (connection));
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+
+ dbus_connection_unref (connection);
+
+ return TRUE;
+ }
+
+ block_connection_until_message_from_bus (context, connection, "reply to AddMatch");
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+
+ dbus_connection_unref (connection);
+
+ return TRUE;
+ }
+
+ dbus_connection_unref (connection);
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "AddMatch", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+
+ goto out;
+ }
+ }
+ else
+ {
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ {
+ ; /* good, expected */
+ _dbus_assert (dbus_message_get_reply_serial (message) == serial);
+ }
+ else
+ {
+ warn_unexpected (connection, message, "method return for AddMatch");
+
+ goto out;
+ }
+ }
+
+ if (!check_no_leftovers (context))
+ goto out;
+
+ retval = TRUE;
+
+ out:
+ dbus_error_free (&error);
+
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_hello_connection (BusContext *context)
+{
+ DBusConnection *connection;
+ DBusError error;
+
+ dbus_error_init (&error);
+
+ connection = dbus_connection_open_private (TEST_CONNECTION, &error);
+ if (connection == NULL)
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (&error);
+ dbus_error_free (&error);
+ return TRUE;
+ }
+
+ if (!bus_setup_debug_client (connection))
+ {
+ dbus_connection_close (connection);
+ dbus_connection_unref (connection);
+ return TRUE;
+ }
+
+ spin_connection_until_authenticated (context, connection);
+
+ if (!check_hello_message (context, connection))
+ return FALSE;
+
+ if (dbus_bus_get_unique_name (connection) == NULL)
+ {
+ /* We didn't successfully register, so we can't
+ * do the usual kill_client_connection() checks
+ */
+ kill_client_connection_unchecked (connection);
+ }
+ else
+ {
+ if (!check_add_match_all (context, connection))
+ return FALSE;
+
+ kill_client_connection (context, connection);
+ }
+
+ return TRUE;
+}
+
+#define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_nonexistent_service_no_auto_start (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+ const char *nonexistent = NONEXISTENT_SERVICE_NAME;
+ dbus_uint32_t flags;
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "StartServiceByName");
+
+ if (message == NULL)
+ return TRUE;
+
+ dbus_message_set_auto_start (message, FALSE);
+
+ flags = 0;
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &nonexistent,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+ block_connection_until_message_from_bus (context, connection, "reply to ActivateService on nonexistent");
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "StartServiceByName", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SERVICE_UNKNOWN))
+ {
+ ; /* good, this is expected also */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+ goto out;
+ }
+ }
+ else
+ {
+ _dbus_warn ("Did not expect to successfully activate %s\n",
+ NONEXISTENT_SERVICE_NAME);
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_nonexistent_service_auto_start (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+
+ message = dbus_message_new_method_call (NONEXISTENT_SERVICE_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Echo");
+
+ if (message == NULL)
+ return TRUE;
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+ block_connection_until_message_from_bus (context, connection, "reply to Echo");
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "Echo message (auto activation)", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SERVICE_UNKNOWN))
+ {
+ ; /* good, this is expected also */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+ goto out;
+ }
+ }
+ else
+ {
+ _dbus_warn ("Did not expect to successfully activate %s\n",
+ NONEXISTENT_SERVICE_NAME);
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+static dbus_bool_t
+check_base_service_activated (BusContext *context,
+ DBusConnection *connection,
+ DBusMessage *initial_message,
+ const char **base_service_p)
+{
+ DBusMessage *message;
+ dbus_bool_t retval;
+ DBusError error;
+ const char *base_service, *base_service_from_bus, *old_owner;
+
+ retval = FALSE;
+
+ dbus_error_init (&error);
+ base_service = NULL;
+ old_owner = NULL;
+ base_service_from_bus = NULL;
+
+ message = initial_message;
+ dbus_message_ref (message);
+
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged"))
+ {
+ CheckServiceOwnerChangedData socd;
+
+ reget_service_name_arg:
+ base_service = NULL;
+ old_owner = NULL;
+ base_service_from_bus = NULL;
+
+ if (!dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &base_service,
+ DBUS_TYPE_STRING, &old_owner,
+ DBUS_TYPE_STRING, &base_service_from_bus,
+ DBUS_TYPE_INVALID))
+ {
+ if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ {
+ dbus_error_free (&error);
+ _dbus_wait_for_memory ();
+ goto reget_service_name_arg;
+ }
+ else
+ {
+ _dbus_warn ("Message %s doesn't have a service name: %s\n",
+ "NameOwnerChanged (creation)",
+ error.message);
+ goto out;
+ }
+ }
+
+ if (*base_service != ':')
+ {
+ _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
+ base_service);
+ goto out;
+ }
+
+ if (strcmp (base_service, base_service_from_bus) != 0)
+ {
+ _dbus_warn ("Expected base service activation, got \"%s\" instead with owner \"%s\"\n",
+ base_service, base_service_from_bus);
+ goto out;
+ }
+
+ if (old_owner[0])
+ {
+ _dbus_warn ("Received an old_owner argument during base service activation, \"%s\"\n",
+ old_owner);
+ goto out;
+ }
+
+ socd.expected_kind = SERVICE_CREATED;
+ socd.expected_service_name = base_service;
+ socd.failed = FALSE;
+ socd.skip_connection = connection;
+ bus_test_clients_foreach (check_service_owner_changed_foreach,
+ &socd);
+
+ if (socd.failed)
+ goto out;
+ }
+ else
+ {
+ warn_unexpected (connection, message, "NameOwnerChanged (creation) for base service");
+
+ goto out;
+ }
+
+ if (base_service_p)
+ *base_service_p = base_service;
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+ dbus_error_free (&error);
+
+ return retval;
+}
+
+static dbus_bool_t
+check_service_activated (BusContext *context,
+ DBusConnection *connection,
+ const char *activated_name,
+ const char *base_service_name,
+ DBusMessage *initial_message)
+{
+ DBusMessage *message;
+ dbus_bool_t retval;
+ DBusError error;
+ dbus_uint32_t activation_result;
+
+ retval = FALSE;
+
+ dbus_error_init (&error);
+
+ message = initial_message;
+ dbus_message_ref (message);
+
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged"))
+ {
+ CheckServiceOwnerChangedData socd;
+ const char *service_name, *base_service_from_bus, *old_owner;
+
+ reget_service_name_arg:
+ service_name = NULL;
+ old_owner = NULL;
+ base_service_from_bus = NULL;
+
+ if (!dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &service_name,
+ DBUS_TYPE_STRING, &old_owner,
+ DBUS_TYPE_STRING, &base_service_from_bus,
+ DBUS_TYPE_INVALID))
+ {
+ if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ {
+ dbus_error_free (&error);
+ _dbus_wait_for_memory ();
+ goto reget_service_name_arg;
+ }
+ else
+ {
+ _dbus_warn ("Message %s doesn't have a service name: %s\n",
+ "NameOwnerChanged (creation)",
+ error.message);
+ goto out;
+ }
+ }
+
+ if (strcmp (service_name, activated_name) != 0)
+ {
+ _dbus_warn ("Expected to see service %s created, saw %s instead\n",
+ activated_name, service_name);
+ goto out;
+ }
+
+ if (strcmp (base_service_name, base_service_from_bus) != 0)
+ {
+ _dbus_warn ("NameOwnerChanged reports wrong base service: %s owner, expected %s instead\n",
+ base_service_from_bus, base_service_name);
+ goto out;
+ }
+
+ if (old_owner[0])
+ {
+ _dbus_warn ("expected a %s, got a %s\n",
+ "NameOwnerChanged (creation)",
+ "NameOwnerChanged (change)");
+ goto out;
+ }
+
+ socd.expected_kind = SERVICE_CREATED;
+ socd.skip_connection = connection;
+ socd.failed = FALSE;
+ socd.expected_service_name = service_name;
+ bus_test_clients_foreach (check_service_owner_changed_foreach,
+ &socd);
+
+ if (socd.failed)
+ goto out;
+
+ dbus_message_unref (message);
+ service_name = NULL;
+ old_owner = NULL;
+ base_service_from_bus = NULL;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Expected a reply to %s, got nothing\n",
+ "StartServiceByName");
+ goto out;
+ }
+ }
+ else
+ {
+ warn_unexpected (connection, message, "NameOwnerChanged for the activated name");
+
+ goto out;
+ }
+
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ {
+ warn_unexpected (connection, message, "reply to StartServiceByName");
+
+ goto out;
+ }
+
+ activation_result = 0;
+ if (!dbus_message_get_args (message, &error,
+ DBUS_TYPE_UINT32, &activation_result,
+ DBUS_TYPE_INVALID))
+ {
+ if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ {
+ _dbus_warn ("Did not have activation result first argument to %s: %s\n",
+ "StartServiceByName", error.message);
+ goto out;
+ }
+
+ dbus_error_free (&error);
+ }
+ else
+ {
+ if (activation_result == DBUS_START_REPLY_SUCCESS)
+ ; /* Good */
+ else if (activation_result == DBUS_START_REPLY_ALREADY_RUNNING)
+ ; /* Good also */
+ else
+ {
+ _dbus_warn ("Activation result was %u, no good.\n",
+ activation_result);
+ goto out;
+ }
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ if (!check_no_leftovers (context))
+ {
+ _dbus_warn ("Messages were left over after verifying existent activation results\n");
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+ dbus_error_free (&error);
+
+ return retval;
+}
+
+static dbus_bool_t
+check_service_auto_activated (BusContext *context,
+ DBusConnection *connection,
+ const char *activated_name,
+ const char *base_service_name,
+ DBusMessage *initial_message)
+{
+ DBusMessage *message;
+ dbus_bool_t retval;
+ DBusError error;
+
+ retval = FALSE;
+
+ dbus_error_init (&error);
+
+ message = initial_message;
+ dbus_message_ref (message);
+
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged"))
+ {
+ const char *service_name;
+ CheckServiceOwnerChangedData socd;
+
+ reget_service_name_arg:
+ if (!dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &service_name,
+ DBUS_TYPE_INVALID))
+ {
+ if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ {
+ dbus_error_free (&error);
+ _dbus_wait_for_memory ();
+ goto reget_service_name_arg;
+ }
+ else
+ {
+ _dbus_warn ("Message %s doesn't have a service name: %s\n",
+ "NameOwnerChanged",
+ error.message);
+ dbus_error_free (&error);
+ goto out;
+ }
+ }
+
+ if (strcmp (service_name, activated_name) != 0)
+ {
_dbus_warn ("Expected to see service %s created, saw %s instead\n",
activated_name, service_name);
- dbus_free (service_name);
goto out;
}
-
- scd.skip_connection = connection;
- scd.failed = FALSE;
- scd.expected_service_name = service_name;
- bus_test_clients_foreach (check_service_created_foreach,
- &scd);
-
- dbus_free (service_name);
- if (scd.failed)
- goto out;
-
+ socd.expected_kind = SERVICE_CREATED;
+ socd.expected_service_name = service_name;
+ socd.failed = FALSE;
+ socd.skip_connection = connection;
+ bus_test_clients_foreach (check_service_owner_changed_foreach,
+ &socd);
+
+ if (socd.failed)
+ goto out;
+
+ /* Note that this differs from regular activation in that we don't get a
+ * reply to ActivateService here.
+ */
+
+ dbus_message_unref (message);
+ message = NULL;
+ service_name = NULL;
+ }
+ else
+ {
+ warn_unexpected (connection, message, "NameOwnerChanged for the activated name");
+
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+static dbus_bool_t
+check_service_deactivated (BusContext *context,
+ DBusConnection *connection,
+ const char *activated_name,
+ const char *base_service)
+{
+ dbus_bool_t retval;
+ CheckServiceOwnerChangedData socd;
+
+ retval = FALSE;
+
+ /* Now we are expecting ServiceOwnerChanged (deletion) messages for the base
+ * service and the activated_name. The base service
+ * notification is required to come last.
+ */
+ socd.expected_kind = SERVICE_DELETED;
+ socd.expected_service_name = activated_name;
+ socd.failed = FALSE;
+ socd.skip_connection = NULL;
+ bus_test_clients_foreach (check_service_owner_changed_foreach,
+ &socd);
+
+ if (socd.failed)
+ goto out;
+
+ socd.expected_kind = SERVICE_DELETED;
+ socd.expected_service_name = base_service;
+ socd.failed = FALSE;
+ socd.skip_connection = NULL;
+ bus_test_clients_foreach (check_service_owner_changed_foreach,
+ &socd);
+
+ if (socd.failed)
+ goto out;
+
+ retval = TRUE;
+
+ out:
+ return retval;
+}
+
+static dbus_bool_t
+check_send_exit_to_service (BusContext *context,
+ DBusConnection *connection,
+ const char *service_name,
+ const char *base_service)
+{
+ dbus_bool_t got_error;
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+
+ _dbus_verbose ("Sending exit message to the test service\n");
+
+ retval = FALSE;
+
+ /* Kill off the test service by sending it a quit message */
+ message = dbus_message_new_method_call (service_name,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Exit");
+
+ if (message == NULL)
+ {
+ /* Do this again; we still need the service to exit... */
+ if (!check_send_exit_to_service (context, connection,
+ service_name, base_service))
+ goto out;
+
+ return TRUE;
+ }
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+
+ /* Do this again; we still need the service to exit... */
+ if (!check_send_exit_to_service (context, connection,
+ service_name, base_service))
+ goto out;
+
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ /* send message */
+ bus_test_run_clients_loop (SEND_PENDING (connection));
+
+ /* read it in and write it out to test service */
+ bus_test_run_bus_loop (context, FALSE);
+
+ /* see if we got an error during message bus dispatching */
+ bus_test_run_clients_loop (FALSE);
+ message = borrow_message_waiting_for_memory (connection);
+ got_error = message != NULL && dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
+ if (message)
+ {
+ dbus_connection_return_message (connection, message);
+ message = NULL;
+ }
+
+ if (!got_error)
+ {
+ /* If no error, wait for the test service to exit */
+ block_connection_until_message_from_bus (context, connection, "test service to exit");
+
+ bus_test_run_everything (context);
+ }
+
+ if (got_error)
+ {
+ message = pop_message_waiting_for_memory (connection);
+ _dbus_assert (message != NULL);
+
+ if (dbus_message_get_reply_serial (message) != serial)
+ {
+ warn_unexpected (connection, message,
+ "error with the correct reply serial");
+ goto out;
+ }
+
+ if (!dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ warn_unexpected (connection, message,
+ "a no memory error from asking test service to exit");
+ goto out;
+ }
+
+ _dbus_verbose ("Got error %s when asking test service to exit\n",
+ dbus_message_get_error_name (message));
+
+ /* Do this again; we still need the service to exit... */
+ if (!check_send_exit_to_service (context, connection,
+ service_name, base_service))
+ goto out;
+ }
+ else
+ {
+ if (!check_service_deactivated (context, connection,
+ service_name, base_service))
+ goto out;
+
+ /* Should now have a NoReply error from the Exit() method
+ * call; it should have come after all the deactivation
+ * stuff.
+ */
+ message = pop_message_waiting_for_memory (connection);
+
+ if (message == NULL)
+ {
+ warn_unexpected (connection, NULL,
+ "reply to Exit() method call");
+ goto out;
+ }
+ if (!dbus_message_is_error (message,
+ DBUS_ERROR_NO_REPLY))
+ {
+ warn_unexpected (connection, message,
+ "NoReply error from Exit() method call");
+ goto out;
+ }
+
+ if (dbus_message_get_reply_serial (message) != serial)
+ {
+ warn_unexpected (connection, message,
+ "error with the correct reply serial");
+ goto out;
+ }
+
+ _dbus_verbose ("Got error %s after test service exited\n",
+ dbus_message_get_error_name (message));
+
+ if (!check_no_leftovers (context))
+ {
+ _dbus_warn ("Messages were left over after %s\n",
+ _DBUS_FUNCTION_NAME);
+ goto out;
+ }
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+static dbus_bool_t
+check_got_error (BusContext *context,
+ DBusConnection *connection,
+ const char *first_error_name,
+ ...)
+{
+ DBusMessage *message;
+ dbus_bool_t retval;
+ va_list ap;
+ dbus_bool_t error_found;
+ const char *error_name;
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not get an expected error\n");
+ goto out;
+ }
+
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
+ {
+ warn_unexpected (connection, message, "an error");
+
+ goto out;
+ }
+
+ error_found = FALSE;
+
+ va_start (ap, first_error_name);
+ error_name = first_error_name;
+ while (error_name != NULL)
+ {
+ if (dbus_message_is_error (message, error_name))
+ {
+ error_found = TRUE;
+ break;
+ }
+ error_name = va_arg (ap, char*);
+ }
+ va_end (ap);
+
+ if (!error_found)
+ {
+ _dbus_warn ("Expected error %s or other, got %s instead\n",
+ first_error_name,
+ dbus_message_get_error_name (message));
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+typedef enum
+{
+ GOT_SERVICE_CREATED,
+ GOT_SERVICE_DELETED,
+ GOT_ERROR,
+ GOT_SOMETHING_ELSE
+} GotServiceInfo;
+
+static GotServiceInfo
+check_got_service_info (DBusMessage *message)
+{
+ GotServiceInfo message_kind;
+
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged"))
+ {
+ DBusError error;
+ const char *service_name, *old_owner, *new_owner;
+ dbus_error_init (&error);
+
+ reget_service_info_data:
+ service_name = NULL;
+ old_owner = NULL;
+ new_owner = NULL;
+
+ dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &service_name,
+ DBUS_TYPE_STRING, &old_owner,
+ DBUS_TYPE_STRING, &new_owner,
+ DBUS_TYPE_INVALID);
+ if (dbus_error_is_set (&error))
+ {
+ if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ {
+ dbus_error_free (&error);
+ goto reget_service_info_data;
+ }
+ else
+ {
+ _dbus_warn ("unexpected arguments for NameOwnerChanged message\n");
+ message_kind = GOT_SOMETHING_ELSE;
+ }
+ }
+ else if (!old_owner[0])
+ message_kind = GOT_SERVICE_CREATED;
+ else if (!new_owner[0])
+ message_kind = GOT_SERVICE_DELETED;
+ else
+ message_kind = GOT_SOMETHING_ELSE;
+
+ dbus_error_free (&error);
+ }
+ else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ message_kind = GOT_ERROR;
+ else
+ message_kind = GOT_SOMETHING_ELSE;
+
+ return message_kind;
+}
+
+#define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_existent_service_no_auto_start (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ DBusMessage *base_service_message;
+ const char *base_service;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+ const char *existent = EXISTENT_SERVICE_NAME;
+ dbus_uint32_t flags;
+
+ base_service_message = NULL;
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "StartServiceByName");
+
+ if (message == NULL)
+ return TRUE;
+
+ dbus_message_set_auto_start (message, FALSE);
+
+ flags = 0;
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &existent,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+
+ /* now wait for the message bus to hear back from the activated
+ * service.
+ */
+ block_connection_until_message_from_bus (context, connection, "activated service to connect");
+
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive any messages after %s %d on %p\n",
+ "StartServiceByName", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+ _dbus_verbose (" (after sending %s)\n", "StartServiceByName");
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_CHILD_EXITED) ||
+ dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_CHILD_SIGNALED) ||
+ dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_EXEC_FAILED))
+ {
+ ; /* good, this is expected also */
+ }
+ else
+ {
+ _dbus_warn ("Did not expect error %s\n",
+ dbus_message_get_error_name (message));
+ goto out;
+ }
+ }
+ else
+ {
+ GotServiceInfo message_kind;
+
+ if (!check_base_service_activated (context, connection,
+ message, &base_service))
+ goto out;
+
+ base_service_message = message;
+ message = NULL;
+
+ /* We may need to block here for the test service to exit or finish up */
+ block_connection_until_message_from_bus (context, connection, "test service to exit or finish up");
+
+ message = dbus_connection_borrow_message (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive any messages after base service creation notification\n");
+ goto out;
+ }
+
+ message_kind = check_got_service_info (message);
+
+ dbus_connection_return_message (connection, message);
+ message = NULL;
+
+ switch (message_kind)
+ {
+ case GOT_SOMETHING_ELSE:
+ _dbus_warn ("Unexpected message after ActivateService "
+ "(should be an error or a service announcement");
+ goto out;
+
+ case GOT_ERROR:
+ if (!check_got_error (context, connection,
+ DBUS_ERROR_SPAWN_CHILD_EXITED,
+ DBUS_ERROR_NO_MEMORY,
+ NULL))
+ goto out;
+ /* A service deleted should be coming along now after this error.
+ * We can also get the error *after* the service deleted.
+ */
+
+ /* fall through */
+
+ case GOT_SERVICE_DELETED:
+ {
+ /* The service started up and got a base address, but then
+ * failed to register under EXISTENT_SERVICE_NAME
+ */
+ CheckServiceOwnerChangedData socd;
+
+ socd.expected_kind = SERVICE_DELETED;
+ socd.expected_service_name = base_service;
+ socd.failed = FALSE;
+ socd.skip_connection = NULL;
+
+ bus_test_clients_foreach (check_service_owner_changed_foreach,
+ &socd);
+
+ if (socd.failed)
+ goto out;
+
+ /* Now we should get an error about the service exiting
+ * if we didn't get it before.
+ */
+ if (message_kind != GOT_ERROR)
+ {
+ block_connection_until_message_from_bus (context, connection, "error about service exiting");
+
+ /* and process everything again */
+ bus_test_run_everything (context);
+
+ if (!check_got_error (context, connection,
+ DBUS_ERROR_SPAWN_CHILD_EXITED,
+ DBUS_ERROR_NO_MEMORY,
+ NULL))
+ goto out;
+ }
+ break;
+ }
+
+ case GOT_SERVICE_CREATED:
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Failed to pop message we just put back! "
+ "should have been a NameOwnerChanged (creation)\n");
+ goto out;
+ }
+
+ if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
+ base_service, message))
+ goto out;
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ if (!check_no_leftovers (context))
+ {
+ _dbus_warn ("Messages were left over after successful activation\n");
+ goto out;
+ }
+
+ if (!check_send_exit_to_service (context, connection,
+ EXISTENT_SERVICE_NAME, base_service))
+ goto out;
+
+ break;
+ }
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ if (base_service_message)
+ dbus_message_unref (base_service_message);
+
+ return retval;
+}
+
+#ifndef DBUS_WIN_FIXME
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_segfault_service_no_auto_start (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+ const char *segv_service;
+ dbus_uint32_t flags;
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "StartServiceByName");
+
+ if (message == NULL)
+ return TRUE;
+
+ dbus_message_set_auto_start (message, FALSE);
+
+ segv_service = "org.freedesktop.DBus.TestSuiteSegfaultService";
+ flags = 0;
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &segv_service,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+ block_connection_until_message_from_bus (context, connection, "reply to activating segfault service");
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "StartServiceByName", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_FAILED))
+ {
+ const char *servicehelper;
+ servicehelper = bus_context_get_servicehelper (context);
+ /* make sure this only happens with the launch helper */
+ _dbus_assert (servicehelper != NULL);
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_CHILD_SIGNALED))
+ {
+ ; /* good, this is expected also */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+
+ goto out;
+ }
+ }
+ else
+ {
+ _dbus_warn ("Did not expect to successfully activate segfault service\n");
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_segfault_service_auto_start (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+
+ message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteSegfaultService",
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Echo");
+
+ if (message == NULL)
+ return TRUE;
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+ block_connection_until_message_from_bus (context, connection, "reply to Echo on segfault service");
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "Echo message (auto activation)", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_CHILD_SIGNALED))
+ {
+ ; /* good, this is expected also */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+
+ goto out;
+ }
+ }
+ else
+ {
+ _dbus_warn ("Did not expect to successfully activate segfault service\n");
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+#endif
+
+#define TEST_ECHO_MESSAGE "Test echo message"
+#define TEST_RUN_HELLO_FROM_SELF_MESSAGE "Test sending message to self"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_existent_hello_from_self (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ const char *text;
+
+ message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "RunHelloFromSelf");
+
+ if (message == NULL)
+ return TRUE;
+
+ text = TEST_RUN_HELLO_FROM_SELF_MESSAGE;
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+
+ /* Note: if this test is run in OOM mode, it will block when the bus
+ * doesn't send a reply due to OOM.
+ */
+ block_connection_until_message_from_bus (context, connection, "reply from running hello from self");
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Failed to pop message! Should have been reply from RunHelloFromSelf message\n");
+ return FALSE;
+ }
+
+ if (dbus_message_get_reply_serial (message) != serial)
+ {
+ _dbus_warn ("Wrong reply serial\n");
+ dbus_message_unref (message);
+ return FALSE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ return TRUE;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_existent_ping (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.DBus.Peer",
+ "Ping");
+
+ if (message == NULL)
+ return TRUE;
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+
+ /* Note: if this test is run in OOM mode, it will block when the bus
+ * doesn't send a reply due to OOM.
+ */
+ block_connection_until_message_from_bus (context, connection, "reply from running Ping");
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Failed to pop message! Should have been reply from Ping message\n");
+ return FALSE;
+ }
+
+ if (dbus_message_get_reply_serial (message) != serial)
+ {
+ _dbus_warn ("Wrong reply serial\n");
+ dbus_message_unref (message);
+ return FALSE;
+ }
+
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ {
+ _dbus_warn ("Unexpected message return during Ping\n");
+ dbus_message_unref (message);
+ return FALSE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ return TRUE;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_existent_get_machine_id (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ const char *machine_id;
+
+ message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.DBus.Peer",
+ "GetMachineId");
+
+ if (message == NULL)
+ return TRUE;
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+
+ /* Note: if this test is run in OOM mode, it will block when the bus
+ * doesn't send a reply due to OOM.
+ */
+ block_connection_until_message_from_bus (context, connection, "reply from running GetMachineId");
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Failed to pop message! Should have been reply from GetMachineId message\n");
+ return FALSE;
+ }
+
+ if (dbus_message_get_reply_serial (message) != serial)
+ {
+ _dbus_warn ("Wrong reply serial\n");
+ dbus_message_unref (message);
+ return FALSE;
+ }
+
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ {
+ _dbus_warn ("Unexpected message return during GetMachineId\n");
+ dbus_message_unref (message);
+ return FALSE;
+ }
+
+ machine_id = NULL;
+ if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &machine_id, DBUS_TYPE_INVALID))
+ {
+ _dbus_warn ("Did not get a machine ID in reply to GetMachineId\n");
+ dbus_message_unref (message);
+ return FALSE;
+ }
+
+ if (machine_id == NULL || strlen (machine_id) != 32)
+ {
+ _dbus_warn ("Machine id looks bogus: '%s'\n", machine_id ? machine_id : "null");
+ dbus_message_unref (message);
+ return FALSE;
+ }
+
+ /* We can't check that the machine id is correct because during make check it is
+ * just made up for each process separately
+ */
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ return TRUE;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_existent_service_auto_start (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ DBusMessage *base_service_message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+ const char *base_service;
+ const char *text;
+
+ base_service_message = NULL;
+
+ message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Echo");
+
+ if (message == NULL)
+ return TRUE;
+
+ text = TEST_ECHO_MESSAGE;
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+
+ /* now wait for the message bus to hear back from the activated
+ * service.
+ */
+ block_connection_until_message_from_bus (context, connection, "reply to Echo on existent service");
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive any messages after auto start %d on %p\n",
+ serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+ _dbus_verbose (" (after sending %s)\n", "auto start");
+
+ /* we should get zero or two ServiceOwnerChanged signals */
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL)
+ {
+ GotServiceInfo message_kind;
+
+ if (!check_base_service_activated (context, connection,
+ message, &base_service))
+ goto out;
+
+ base_service_message = message;
+ message = NULL;
+
+ /* We may need to block here for the test service to exit or finish up */
+ block_connection_until_message_from_bus (context, connection, "service to exit");
+
+ /* Should get a service creation notification for the activated
+ * service name, or a service deletion on the base service name
+ */
+ message = dbus_connection_borrow_message (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("No message after auto activation "
+ "(should be a service announcement)\n");
+ dbus_connection_return_message (connection, message);
+ message = NULL;
+ goto out;
+ }
+
+ message_kind = check_got_service_info (message);
+
+ dbus_connection_return_message (connection, message);
+ message = NULL;
+
+ switch (message_kind)
+ {
+ case GOT_SERVICE_CREATED:
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Failed to pop message we just put back! "
+ "should have been a NameOwnerChanged (creation)\n");
+ goto out;
+ }
+
+ /* Check that ServiceOwnerChanged (creation) was correctly received */
+ if (!check_service_auto_activated (context, connection, EXISTENT_SERVICE_NAME,
+ base_service, message))
+ goto out;
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ break;
+
+ case GOT_SERVICE_DELETED:
+ {
+ /* The service started up and got a base address, but then
+ * failed to register under EXISTENT_SERVICE_NAME
+ */
+ CheckServiceOwnerChangedData socd;
+
+ socd.expected_kind = SERVICE_DELETED;
+ socd.expected_service_name = base_service;
+ socd.failed = FALSE;
+ socd.skip_connection = NULL;
+ bus_test_clients_foreach (check_service_owner_changed_foreach,
+ &socd);
+
+ if (socd.failed)
+ goto out;
+
+ break;
+ }
+
+ case GOT_ERROR:
+ case GOT_SOMETHING_ELSE:
+ _dbus_warn ("Unexpected message after auto activation\n");
+ goto out;
+ }
+ }
+
+ /* OK, now we've dealt with ServiceOwnerChanged signals, now should
+ * come the method reply (or error) from the initial method call
+ */
+
+ /* Note: if this test is run in OOM mode, it will block when the bus
+ * doesn't send a reply due to OOM.
+ */
+ block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation");
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
+ goto out;
+ }
+
+ if (dbus_message_get_reply_serial (message) != serial)
+ {
+ _dbus_warn ("Wrong reply serial\n");
+ goto out;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ if (!check_existent_ping (context, connection))
+ goto out;
+
+ if (!check_existent_get_machine_id (context, connection))
+ goto out;
+
+ if (!check_existent_hello_from_self (context, connection))
+ goto out;
+
+ if (!check_send_exit_to_service (context, connection,
+ EXISTENT_SERVICE_NAME,
+ base_service))
+ goto out;
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ if (base_service_message)
+ dbus_message_unref (base_service_message);
+
+ return retval;
+}
+
+#define SERVICE_FILE_MISSING_NAME "org.freedesktop.DBus.TestSuiteEchoServiceDotServiceFileDoesNotExist"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_launch_service_file_missing (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+
+ message = dbus_message_new_method_call (SERVICE_FILE_MISSING_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Echo");
+
+ if (message == NULL)
+ return TRUE;
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+ block_connection_until_message_from_bus (context, connection, "reply to service file missing should fail to auto-start");
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "Echo message (auto activation)", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SERVICE_UNKNOWN))
+ {
+ _dbus_verbose("got service unknown\n");
+ ; /* good, this is expected (only valid when using launch helper) */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+
+ goto out;
+ }
+ }
+ else
+ {
+ _dbus_warn ("Did not expect to successfully auto-start missing service\n");
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+#define SERVICE_USER_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoUser"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_launch_service_user_missing (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+
+ message = dbus_message_new_method_call (SERVICE_USER_MISSING_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Echo");
+
+ if (message == NULL)
+ return TRUE;
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
dbus_message_unref (message);
- message = pop_message_waiting_for_memory (connection);
- if (message == NULL)
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+ block_connection_until_message_from_bus (context, connection,
+ "reply to service which should fail to auto-start (missing User)");
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_warn ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "Echo message (auto activation)", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Expected a reply to %s, got nothing\n",
- "ActivateService");
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_FILE_INVALID))
+ {
+ _dbus_verbose("got service file invalid\n");
+ ; /* good, this is expected (only valid when using launch helper) */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+
+ goto out;
+ }
+ }
+ else
+ {
+ _dbus_warn ("Did not expect to successfully auto-start missing service\n");
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+#define SERVICE_EXEC_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoExec"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_launch_service_exec_missing (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+
+ message = dbus_message_new_method_call (SERVICE_EXEC_MISSING_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Echo");
+
+ if (message == NULL)
+ return TRUE;
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+ block_connection_until_message_from_bus (context, connection,
+ "reply to service which should fail to auto-start (missing Exec)");
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_warn ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "Echo message (auto activation)", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SERVICE_UNKNOWN))
+ {
+ _dbus_verbose("could not activate as invalid service file was not added\n");
+ ; /* good, this is expected as we shouldn't have been added to
+ * the activation list with a missing Exec key */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_FILE_INVALID))
+ {
+ _dbus_verbose("got service file invalid\n");
+ ; /* good, this is allowed, and is the message passed back from the
+ * launch helper */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+
goto out;
}
}
else
{
- warn_unexpected (connection, message, "ServiceCreated for the activated name");
-
- goto out;
+ _dbus_warn ("Did not expect to successfully auto-start missing service\n");
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+#define SERVICE_SERVICE_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoService"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_launch_service_service_missing (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+
+ message = dbus_message_new_method_call (SERVICE_SERVICE_MISSING_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Echo");
+
+ if (message == NULL)
+ return TRUE;
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
}
-
- if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+ block_connection_until_message_from_bus (context, connection,
+ "reply to service which should fail to auto-start (missing Service)");
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
{
- warn_unexpected (connection, message, "reply to ActivateService");
+ _dbus_warn ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "Echo message (auto activation)", serial, connection);
goto out;
}
- activation_result = 0;
- if (!dbus_message_get_args (message, &error,
- DBUS_TYPE_UINT32, &activation_result,
- DBUS_TYPE_INVALID))
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
{
- if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Did not have activation result first argument to %s: %s\n",
- "ActivateService", error.message);
- dbus_error_free (&error);
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
goto out;
}
- dbus_error_free (&error);
- }
- else
- {
- if (activation_result == DBUS_ACTIVATION_REPLY_ACTIVATED)
- ; /* Good */
- else if (activation_result == DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE)
- ; /* Good also */
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SERVICE_UNKNOWN))
+ {
+ _dbus_verbose("could not activate as invalid service file was not added\n");
+ ; /* good, this is expected as we shouldn't have been added to
+ * the activation list with a missing Exec key */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_FILE_INVALID))
+ {
+ _dbus_verbose("got service file invalid\n");
+ ; /* good, this is allowed, and is the message passed back from the
+ * launch helper */
+ }
else
{
- _dbus_warn ("Activation result was 0x%x, no good.\n",
- activation_result);
+ warn_unexpected (connection, message, "not this error");
+
goto out;
}
}
-
- dbus_message_unref (message);
- message = NULL;
-
- if (!check_no_leftovers (context))
+ else
{
- _dbus_warn ("Messages were left over after verifying existent activation results\n");
+ _dbus_warn ("Did not expect to successfully auto-start missing service\n");
goto out;
}
retval = TRUE;
-
+
out:
if (message)
dbus_message_unref (message);
-
+
return retval;
}
+#define SHELL_FAIL_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceFail"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
static dbus_bool_t
-check_service_deactivated (BusContext *context,
- DBusConnection *connection,
- const char *activated_name,
- const char *base_service)
+check_shell_fail_service_auto_start (BusContext *context,
+ DBusConnection *connection)
{
DBusMessage *message;
+ dbus_uint32_t serial;
dbus_bool_t retval;
- DBusError error;
- CheckServiceDeletedData csdd;
+ message = dbus_message_new_method_call (SHELL_FAIL_SERVICE_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Echo");
+
+ if (message == NULL)
+ return TRUE;
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
message = NULL;
+
+ bus_test_run_everything (context);
+ block_connection_until_message_from_bus (context, connection, "reply to shell Echo on service which should fail to auto-start");
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+ return TRUE;
+ }
+
retval = FALSE;
-
- dbus_error_init (&error);
- /* Now we are expecting ServiceDeleted messages for the base
- * service and the activated_name. The base service
- * notification is required to come last.
- */
- csdd.expected_service_name = activated_name;
- csdd.failed = FALSE;
- bus_test_clients_foreach (check_service_deleted_foreach,
- &csdd);
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "Echo message (auto activation)", serial, connection);
+ goto out;
+ }
- if (csdd.failed)
- goto out;
-
- csdd.expected_service_name = base_service;
- csdd.failed = FALSE;
- bus_test_clients_foreach (check_service_deleted_foreach,
- &csdd);
+ verbose_message_received (connection, message);
- if (csdd.failed)
- goto out;
-
- if (!check_no_leftovers (context))
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_INVALID_ARGS))
+ {
+ _dbus_verbose("got invalid args\n");
+ ; /* good, this is expected also */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+
+ goto out;
+ }
+ }
+ else
{
- _dbus_warn ("Messages were left over after verifying results of service exiting\n");
+ _dbus_warn ("Did not expect to successfully auto-start shell fail service\n");
goto out;
}
retval = TRUE;
-
+
out:
if (message)
dbus_message_unref (message);
-
+
return retval;
}
+#define SHELL_SUCCESS_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
static dbus_bool_t
-check_send_exit_to_service (BusContext *context,
- DBusConnection *connection,
- const char *service_name,
- const char *base_service)
+check_shell_service_success_auto_start (BusContext *context,
+ DBusConnection *connection)
{
- dbus_bool_t got_error;
DBusMessage *message;
+ DBusMessage *base_service_message;
dbus_uint32_t serial;
dbus_bool_t retval;
-
- _dbus_verbose ("Sending exit message to the test service\n");
+ const char *base_service;
+ const char *argv[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
- retval = FALSE;
-
- /* Kill off the test service by sending it a quit message */
- message = dbus_message_new_method_call (service_name,
+ base_service_message = NULL;
+
+ message = dbus_message_new_method_call (SHELL_SUCCESS_SERVICE_NAME,
"/org/freedesktop/TestSuite",
"org.freedesktop.TestSuite",
- "Exit");
-
+ "Echo");
+
if (message == NULL)
- {
- /* Do this again; we still need the service to exit... */
- if (!check_send_exit_to_service (context, connection,
- service_name, base_service))
- goto out;
-
- return TRUE;
- }
-
+ return TRUE;
+
if (!dbus_connection_send (connection, message, &serial))
{
dbus_message_unref (message);
-
- /* Do this again; we still need the service to exit... */
- if (!check_send_exit_to_service (context, connection,
- service_name, base_service))
- goto out;
-
return TRUE;
}
dbus_message_unref (message);
message = NULL;
- /* send message */
- bus_test_run_clients_loop (TRUE);
+ bus_test_run_everything (context);
- /* read it in and write it out to test service */
- bus_test_run_bus_loop (context, FALSE);
+ /* now wait for the message bus to hear back from the activated
+ * service.
+ */
+ block_connection_until_message_from_bus (context, connection, "reply to Echo on shell success service");
+ bus_test_run_everything (context);
- /* see if we got an error during message bus dispatching */
- bus_test_run_clients_loop (FALSE);
- message = dbus_connection_borrow_message (connection);
- got_error = message != NULL && dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
- if (message)
+ if (!dbus_connection_get_is_connected (connection))
{
- dbus_connection_return_message (connection, message);
- message = NULL;
+ _dbus_verbose ("connection was disconnected\n");
+ return TRUE;
}
-
- if (!got_error)
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
{
- /* If no error, wait for the test service to exit */
- block_connection_until_message_from_bus (context, connection);
-
- bus_test_run_everything (context);
+ _dbus_warn ("Did not receive any messages after auto start %d on %p\n",
+ serial, connection);
+ goto out;
}
- if (got_error)
+ verbose_message_received (connection, message);
+ _dbus_verbose (" (after sending %s)\n", "auto start");
+
+ /* we should get zero or two ServiceOwnerChanged signals */
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL)
{
- message = pop_message_waiting_for_memory (connection);
- _dbus_assert (message != NULL);
+ GotServiceInfo message_kind;
- if (!dbus_message_is_error (message,
- DBUS_ERROR_NO_MEMORY))
+ if (!check_base_service_activated (context, connection,
+ message, &base_service))
+ goto out;
+
+ base_service_message = message;
+ message = NULL;
+
+ /* We may need to block here for the test service to exit or finish up */
+ block_connection_until_message_from_bus (context, connection, "service to exit");
+
+ /* Should get a service creation notification for the activated
+ * service name, or a service deletion on the base service name
+ */
+ message = dbus_connection_borrow_message (connection);
+ if (message == NULL)
{
- warn_unexpected (connection, message,
- "a no memory error from asking test service to exit");
+ _dbus_warn ("No message after auto activation "
+ "(should be a service announcement)\n");
+ dbus_connection_return_message (connection, message);
+ message = NULL;
goto out;
}
- _dbus_verbose ("Got error %s when asking test service to exit\n",
- dbus_message_get_error_name (message));
+ message_kind = check_got_service_info (message);
- /* Do this again; we still need the service to exit... */
- if (!check_send_exit_to_service (context, connection,
- service_name, base_service))
- goto out;
+ dbus_connection_return_message (connection, message);
+ message = NULL;
+
+ switch (message_kind)
+ {
+ case GOT_SERVICE_CREATED:
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Failed to pop message we just put back! "
+ "should have been a NameOwnerChanged (creation)\n");
+ goto out;
+ }
+
+ /* Check that ServiceOwnerChanged (creation) was correctly received */
+ if (!check_service_auto_activated (context, connection, SHELL_SUCCESS_SERVICE_NAME,
+ base_service, message))
+ goto out;
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ break;
+
+ case GOT_SERVICE_DELETED:
+ {
+ /* The service started up and got a base address, but then
+ * failed to register under SHELL_SUCCESS_SERVICE_NAME
+ */
+ CheckServiceOwnerChangedData socd;
+
+ socd.expected_kind = SERVICE_DELETED;
+ socd.expected_service_name = base_service;
+ socd.failed = FALSE;
+ socd.skip_connection = NULL;
+ bus_test_clients_foreach (check_service_owner_changed_foreach,
+ &socd);
+
+ if (socd.failed)
+ goto out;
+
+ break;
+ }
+
+ case GOT_ERROR:
+ case GOT_SOMETHING_ELSE:
+ _dbus_warn ("Unexpected message after auto activation\n");
+ goto out;
+ }
}
- else
+
+ /* OK, now we've dealt with ServiceOwnerChanged signals, now should
+ * come the method reply (or error) from the initial method call
+ */
+
+ /* Note: if this test is run in OOM mode, it will block when the bus
+ * doesn't send a reply due to OOM.
+ */
+ block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation");
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
+ goto out;
+ }
+
+ if (dbus_message_get_reply_serial (message) != serial)
{
- if (!check_service_deactivated (context, connection,
- service_name, base_service))
- goto out;
+ _dbus_warn ("Wrong reply serial\n");
+ goto out;
}
- retval = TRUE;
-
- out:
- if (message)
- dbus_message_unref (message);
-
- return retval;
-}
+ if (!dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &argv[0],
+ DBUS_TYPE_STRING, &argv[1],
+ DBUS_TYPE_STRING, &argv[2],
+ DBUS_TYPE_STRING, &argv[3],
+ DBUS_TYPE_STRING, &argv[4],
+ DBUS_TYPE_STRING, &argv[5],
+ DBUS_TYPE_STRING, &argv[6],
+ DBUS_TYPE_INVALID))
+ {
+ _dbus_warn ("Error getting arguments from return\n");
+ goto out;
+ }
-static dbus_bool_t
-check_got_error (BusContext *context,
- DBusConnection *connection,
- const char *first_error_name,
- ...)
-{
- DBusMessage *message;
- dbus_bool_t retval;
- va_list ap;
- dbus_bool_t error_found;
- const char *error_name;
-
- retval = FALSE;
-
- message = pop_message_waiting_for_memory (connection);
- if (message == NULL)
+ /* don't worry about arg[0] as it may be different
+ depending on the path to the tests
+ */
+ if (strcmp("-test", argv[1]) != 0)
{
- _dbus_warn ("Did not get an expected error\n");
+ _dbus_warn ("Unexpected argv[1] in shell success service test (expected: %s, got: %s)\n",
+ "-test", argv[1]);
goto out;
}
- if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
+ if (strcmp("that", argv[2]) != 0)
{
- warn_unexpected (connection, message, "an error");
+ _dbus_warn ("Unexpected argv[2] in shell success service test (expected: %s, got: %s)\n",
+ "that", argv[2]);
+ goto out;
+ }
+ if (strcmp("we get", argv[3]) != 0)
+ {
+ _dbus_warn ("Unexpected argv[3] in shell success service test (expected: %s, got: %s)\n",
+ "we get", argv[3]);
goto out;
}
- error_found = FALSE;
+ if (strcmp("back", argv[4]) != 0)
+ {
+ _dbus_warn ("Unexpected argv[4] in shell success service test (expected: %s, got: %s)\n",
+ "back", argv[4]);
+ goto out;
+ }
- va_start (ap, first_error_name);
- error_name = first_error_name;
- while (error_name != NULL)
+ if (strcmp("--what", argv[5]) != 0)
{
- if (dbus_message_is_error (message, error_name))
- {
- error_found = TRUE;
- break;
- }
- error_name = va_arg (ap, char*);
+ _dbus_warn ("Unexpected argv[5] in shell success service test (expected: %s, got: %s)\n",
+ "--what", argv[5]);
+ goto out;
}
- va_end (ap);
- if (!error_found)
+ if (strcmp("we put in", argv[6]) != 0)
{
- _dbus_warn ("Expected error %s or other, got %s instead\n",
- first_error_name,
- dbus_message_get_error_name (message));
+ _dbus_warn ("Unexpected argv[6] in shell success service test (expected: %s, got: %s)\n",
+ "we put in", argv[6]);
goto out;
}
+ dbus_message_unref (message);
+ message = NULL;
+
+ if (!check_send_exit_to_service (context, connection,
+ SHELL_SUCCESS_SERVICE_NAME,
+ base_service))
+ goto out;
+
retval = TRUE;
-
+
out:
if (message)
dbus_message_unref (message);
-
+
+ if (base_service_message)
+ dbus_message_unref (base_service_message);
+
return retval;
}
-
-#define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
-/* returns TRUE if the correct thing happens,
- * but the correct thing may include OOM errors.
- */
+typedef struct
+{
+ Check1Func func;
+ BusContext *context;
+} Check1Data;
+
static dbus_bool_t
-check_existent_service_activation (BusContext *context,
- DBusConnection *connection)
+check_oom_check1_func (void *data)
+{
+ Check1Data *d = data;
+
+ if (! (* d->func) (d->context))
+ return FALSE;
+
+ if (!check_no_leftovers (d->context))
+ {
+ _dbus_warn ("Messages were left over, should be covered by test suite\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+check1_try_iterations (BusContext *context,
+ const char *description,
+ Check1Func func)
+{
+ Check1Data d;
+
+ d.func = func;
+ d.context = context;
+
+ if (!_dbus_test_oom_handling (description, check_oom_check1_func,
+ &d))
+ _dbus_assert_not_reached ("test failed");
+}
+
+static dbus_bool_t
+check_get_services (BusContext *context,
+ DBusConnection *connection,
+ const char *method,
+ char ***services,
+ int *len)
{
DBusMessage *message;
dbus_uint32_t serial;
dbus_bool_t retval;
DBusError error;
- char *base_service;
+ char **srvs;
+ int l;
- base_service = NULL;
-
+ retval = FALSE;
dbus_error_init (&error);
-
- message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
- DBUS_PATH_ORG_FREEDESKTOP_DBUS,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
- "ActivateService");
+ message = NULL;
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ method);
if (message == NULL)
return TRUE;
- if (!dbus_message_append_args (message,
- DBUS_TYPE_STRING, EXISTENT_SERVICE_NAME,
- DBUS_TYPE_UINT32, 0,
- DBUS_TYPE_INVALID))
- {
- dbus_message_unref (message);
- return TRUE;
- }
-
if (!dbus_connection_send (connection, message, &serial))
{
dbus_message_unref (message);
return TRUE;
}
+ /* send our message */
+ bus_test_run_clients_loop (SEND_PENDING (connection));
+
dbus_message_unref (message);
message = NULL;
- bus_test_run_everything (context);
-
- /* now wait for the message bus to hear back from the activated
- * service.
- */
- block_connection_until_message_from_bus (context, connection);
-
- bus_test_run_everything (context);
+ dbus_connection_ref (connection); /* because we may get disconnected */
+ block_connection_until_message_from_bus (context, connection, "reply to ListActivatableNames/ListNames");
if (!dbus_connection_get_is_connected (connection))
{
_dbus_verbose ("connection was disconnected\n");
+
+ dbus_connection_unref (connection);
+
return TRUE;
}
-
- retval = FALSE;
-
+
+ dbus_connection_unref (connection);
+
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive any messages after %s %d on %p\n",
- "ActivateService", serial, connection);
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ method, serial, connection);
goto out;
}
verbose_message_received (connection, message);
- _dbus_verbose (" (after sending %s)\n", "ActivateService");
if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
{
- if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
- {
- _dbus_warn ("Message has wrong sender %s\n",
- dbus_message_get_sender (message) ?
- dbus_message_get_sender (message) : "(none)");
- goto out;
- }
-
- if (dbus_message_is_error (message,
- DBUS_ERROR_NO_MEMORY))
- {
- ; /* good, this is a valid response */
- }
- else if (dbus_message_is_error (message,
- DBUS_ERROR_SPAWN_CHILD_EXITED))
- {
- ; /* good, this is expected also */
- }
+ if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
else
- {
- _dbus_warn ("Did not expect error %s\n",
- dbus_message_get_error_name (message));
- goto out;
- }
+ {
+ warn_unexpected (connection, message, "not this error");
+
+ goto out;
+ }
}
else
{
- dbus_bool_t got_service_deleted;
- dbus_bool_t got_error;
-
- if (!check_base_service_activated (context, connection,
- message, &base_service))
- goto out;
-
- dbus_message_unref (message);
- message = NULL;
-
- /* We may need to block here for the test service to exit or finish up */
- block_connection_until_message_from_bus (context, connection);
-
- message = dbus_connection_borrow_message (connection);
- if (message == NULL)
- {
- _dbus_warn ("Did not receive any messages after base service creation notification\n");
- goto out;
- }
-
- got_service_deleted = dbus_message_is_signal (message,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
- "ServiceDeleted");
- got_error = dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
-
- dbus_connection_return_message (connection, message);
- message = NULL;
-
- if (got_error)
- {
- if (!check_got_error (context, connection,
- DBUS_ERROR_SPAWN_CHILD_EXITED,
- DBUS_ERROR_NO_MEMORY,
- NULL))
- goto out;
-
- /* A service deleted should be coming along now after this error.
- * We can also get the error *after* the service deleted.
- */
- got_service_deleted = TRUE;
- }
-
- if (got_service_deleted)
- {
- /* The service started up and got a base address, but then
- * failed to register under EXISTENT_SERVICE_NAME
- */
- CheckServiceDeletedData csdd;
-
- csdd.expected_service_name = base_service;
- csdd.failed = FALSE;
- bus_test_clients_foreach (check_service_deleted_foreach,
- &csdd);
-
- if (csdd.failed)
- goto out;
-
- /* Now we should get an error about the service exiting
- * if we didn't get it before.
- */
- if (!got_error)
- {
- block_connection_until_message_from_bus (context, connection);
-
- /* and process everything again */
- bus_test_run_everything (context);
-
- if (!check_got_error (context, connection,
- DBUS_ERROR_SPAWN_CHILD_EXITED,
- NULL))
- goto out;
- }
- }
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ {
+ ; /* good, expected */
+ }
else
- {
- message = pop_message_waiting_for_memory (connection);
- if (message == NULL)
- {
- _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
- goto out;
- }
-
- if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
- base_service, message))
- goto out;
-
- dbus_message_unref (message);
- message = NULL;
+ {
+ warn_unexpected (connection, message,
+ "method_return for ListActivatableNames/ListNames");
+ goto out;
+ }
- if (!check_no_leftovers (context))
- {
- _dbus_warn ("Messages were left over after successful activation\n");
- goto out;
- }
+ retry_get_property:
- if (!check_send_exit_to_service (context, connection,
- EXISTENT_SERVICE_NAME, base_service))
- goto out;
- }
+ if (!dbus_message_get_args (message, &error,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING,
+ &srvs, &l,
+ DBUS_TYPE_INVALID))
+ {
+ if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ {
+ _dbus_verbose ("no memory to list services by %s\n", method);
+ dbus_error_free (&error);
+ _dbus_wait_for_memory ();
+ goto retry_get_property;
+ }
+ else
+ {
+ _dbus_assert (dbus_error_is_set (&error));
+ _dbus_warn ("Did not get the expected DBUS_TYPE_ARRAY from %s\n", method);
+ goto out;
+ }
+ } else {
+ *services = srvs;
+ *len = l;
+ }
}
-
+
+ if (!check_no_leftovers (context))
+ goto out;
+
retval = TRUE;
-
+
out:
+ dbus_error_free (&error);
+
if (message)
dbus_message_unref (message);
- if (base_service)
- dbus_free (base_service);
-
return retval;
}
* but the correct thing may include OOM errors.
*/
static dbus_bool_t
-check_segfault_service_activation (BusContext *context,
- DBusConnection *connection)
+check_list_services (BusContext *context,
+ DBusConnection *connection)
{
- DBusMessage *message;
+ DBusMessage *message;
+ DBusMessage *base_service_message;
+ const char *base_service;
dbus_uint32_t serial;
- dbus_bool_t retval;
- DBusError error;
-
- dbus_error_init (&error);
-
- message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
- DBUS_PATH_ORG_FREEDESKTOP_DBUS,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
- "ActivateService");
+ dbus_bool_t retval;
+ const char *existent = EXISTENT_SERVICE_NAME;
+ dbus_uint32_t flags;
+ char **services;
+ int len;
+
+ _dbus_verbose ("check_list_services for %p\n", connection);
+
+ if (!check_get_services (context, connection, "ListActivatableNames", &services, &len))
+ {
+ return TRUE;
+ }
+
+ if (!_dbus_string_array_contains ((const char **)services, existent))
+ {
+ _dbus_warn ("Did not get the expected %s from ListActivatableNames\n", existent);
+ dbus_free_string_array (services);
+ return FALSE;
+ }
+
+ dbus_free_string_array (services);
+
+ base_service_message = NULL;
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "StartServiceByName");
if (message == NULL)
return TRUE;
+ dbus_message_set_auto_start (message, FALSE);
+
+ flags = 0;
if (!dbus_message_append_args (message,
- DBUS_TYPE_STRING,
- "org.freedesktop.DBus.TestSuiteSegfaultService",
- DBUS_TYPE_UINT32, 0,
- DBUS_TYPE_INVALID))
+ DBUS_TYPE_STRING, &existent,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_INVALID))
{
dbus_message_unref (message);
return TRUE;
}
-
+
if (!dbus_connection_send (connection, message, &serial))
{
dbus_message_unref (message);
message = NULL;
bus_test_run_everything (context);
- block_connection_until_message_from_bus (context, connection);
+
+ /* now wait for the message bus to hear back from the activated
+ * service.
+ */
+ block_connection_until_message_from_bus (context, connection, "activated service to connect");
+
bus_test_run_everything (context);
if (!dbus_connection_get_is_connected (connection))
_dbus_verbose ("connection was disconnected\n");
return TRUE;
}
-
+
retval = FALSE;
-
+
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
- "ActivateService", serial, connection);
+ _dbus_warn ("Did not receive any messages after %s %d on %p\n",
+ "StartServiceByName", serial, connection);
goto out;
}
verbose_message_received (connection, message);
+ _dbus_verbose (" (after sending %s)\n", "StartServiceByName");
if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
{
- if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
- {
- _dbus_warn ("Message has wrong sender %s\n",
- dbus_message_get_sender (message) ?
- dbus_message_get_sender (message) : "(none)");
- goto out;
- }
-
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
if (dbus_message_is_error (message,
- DBUS_ERROR_NO_MEMORY))
- {
- ; /* good, this is a valid response */
- }
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
else if (dbus_message_is_error (message,
- DBUS_ERROR_SPAWN_CHILD_SIGNALED))
- {
- ; /* good, this is expected also */
- }
+ DBUS_ERROR_SPAWN_CHILD_EXITED) ||
+ dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_CHILD_SIGNALED) ||
+ dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_EXEC_FAILED))
+ {
+ ; /* good, this is expected also */
+ }
else
- {
- warn_unexpected (connection, message, "not this error");
-
- goto out;
- }
+ {
+ _dbus_warn ("Did not expect error %s\n",
+ dbus_message_get_error_name (message));
+ goto out;
+ }
}
else
{
- _dbus_warn ("Did not expect to successfully activate segfault service\n");
- goto out;
- }
+ GotServiceInfo message_kind;
- retval = TRUE;
-
- out:
- if (message)
- dbus_message_unref (message);
-
- return retval;
-}
+ if (!check_base_service_activated (context, connection,
+ message, &base_service))
+ goto out;
-typedef struct
-{
- Check1Func func;
- BusContext *context;
-} Check1Data;
+ base_service_message = message;
+ message = NULL;
-static dbus_bool_t
-check_oom_check1_func (void *data)
-{
- Check1Data *d = data;
+ /* We may need to block here for the test service to exit or finish up */
+ block_connection_until_message_from_bus (context, connection, "test service to exit or finish up");
- if (! (* d->func) (d->context))
- return FALSE;
-
- if (!check_no_leftovers (d->context))
+ message = dbus_connection_borrow_message (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive any messages after base service creation notification\n");
+ goto out;
+ }
+
+ message_kind = check_got_service_info (message);
+
+ dbus_connection_return_message (connection, message);
+ message = NULL;
+
+ switch (message_kind)
+ {
+ case GOT_SOMETHING_ELSE:
+ case GOT_ERROR:
+ case GOT_SERVICE_DELETED:
+ _dbus_warn ("Unexpected message after ActivateService "
+ "(should be an error or a service announcement)\n");
+ goto out;
+
+ case GOT_SERVICE_CREATED:
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Failed to pop message we just put back! "
+ "should have been a NameOwnerChanged (creation)\n");
+ goto out;
+ }
+
+ if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
+ base_service, message))
+ goto out;
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ if (!check_no_leftovers (context))
+ {
+ _dbus_warn ("Messages were left over after successful activation\n");
+ goto out;
+ }
+
+ break;
+ }
+ }
+
+ if (!check_get_services (context, connection, "ListNames", &services, &len))
{
- _dbus_warn ("Messages were left over, should be covered by test suite\n");
- return FALSE;
+ return TRUE;
}
- return TRUE;
-}
+ if (!_dbus_string_array_contains ((const char **)services, existent))
+ {
+ _dbus_warn ("Did not get the expected %s from ListNames\n", existent);
+ goto out;
+ }
-static void
-check1_try_iterations (BusContext *context,
- const char *description,
- Check1Func func)
-{
- Check1Data d;
+ dbus_free_string_array (services);
- d.func = func;
- d.context = context;
+ if (!check_send_exit_to_service (context, connection,
+ EXISTENT_SERVICE_NAME, base_service))
+ goto out;
- if (!_dbus_test_oom_handling (description, check_oom_check1_func,
- &d))
- _dbus_assert_not_reached ("test failed");
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ if (base_service_message)
+ dbus_message_unref (base_service_message);
+
+ return retval;
}
typedef struct
if (! (* d->func) (d->context, d->connection))
return FALSE;
-
+
if (!check_no_leftovers (d->context))
{
- _dbus_warn ("Messages were left over, should be covered by test suite");
+ _dbus_warn ("Messages were left over, should be covered by test suite\n");
return FALSE;
}
d.func = func;
d.context = context;
d.connection = connection;
-
+
if (!_dbus_test_oom_handling (description, check_oom_check2_func,
&d))
- _dbus_assert_not_reached ("test failed");
+ {
+ _dbus_warn ("%s failed during oom\n", description);
+ _dbus_assert_not_reached ("test failed");
+ }
}
-dbus_bool_t
-bus_dispatch_test (const DBusString *test_data_dir)
+static dbus_bool_t
+setenv_TEST_LAUNCH_HELPER_CONFIG(const DBusString *test_data_dir,
+ const char *filename)
+{
+ DBusString full;
+ DBusString file;
+
+ if (!_dbus_string_init (&full))
+ return FALSE;
+
+ if (!_dbus_string_copy (test_data_dir, 0, &full, 0))
+ {
+ _dbus_string_free (&full);
+ return FALSE;
+ }
+
+ _dbus_string_init_const (&file, filename);
+
+ if (!_dbus_concat_dir_and_file (&full, &file))
+ {
+ _dbus_string_free (&full);
+ return FALSE;
+ }
+
+ _dbus_verbose ("Setting TEST_LAUNCH_HELPER_CONFIG to '%s'\n",
+ _dbus_string_get_const_data (&full));
+
+ _dbus_setenv ("TEST_LAUNCH_HELPER_CONFIG", _dbus_string_get_const_data (&full));
+
+ _dbus_string_free (&full);
+
+ return TRUE;
+}
+
+static dbus_bool_t
+bus_dispatch_test_conf (const DBusString *test_data_dir,
+ const char *filename,
+ dbus_bool_t use_launcher)
{
BusContext *context;
DBusConnection *foo;
DBusConnection *baz;
DBusError error;
+ /* save the config name for the activation helper */
+ if (!setenv_TEST_LAUNCH_HELPER_CONFIG (test_data_dir, filename))
+ _dbus_assert_not_reached ("no memory setting TEST_LAUNCH_HELPER_CONFIG");
+
dbus_error_init (&error);
-
- context = bus_context_new_test (test_data_dir,
- "valid-config-files/debug-allow-all.conf");
+
+ context = bus_context_new_test (test_data_dir, filename);
if (context == NULL)
return FALSE;
-
- foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
+
+ foo = dbus_connection_open_private (TEST_CONNECTION, &error);
if (foo == NULL)
_dbus_assert_not_reached ("could not alloc connection");
if (!bus_setup_debug_client (foo))
_dbus_assert_not_reached ("could not set up connection");
+ spin_connection_until_authenticated (context, foo);
+
if (!check_hello_message (context, foo))
_dbus_assert_not_reached ("hello message failed");
+ if (!check_double_hello_message (context, foo))
+ _dbus_assert_not_reached ("double hello message failed");
+
if (!check_add_match_all (context, foo))
_dbus_assert_not_reached ("AddMatch message failed");
-
- bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
+
+ bar = dbus_connection_open_private (TEST_CONNECTION, &error);
if (bar == NULL)
_dbus_assert_not_reached ("could not alloc connection");
if (!bus_setup_debug_client (bar))
_dbus_assert_not_reached ("could not set up connection");
+ spin_connection_until_authenticated (context, bar);
+
if (!check_hello_message (context, bar))
_dbus_assert_not_reached ("hello message failed");
if (!check_add_match_all (context, bar))
_dbus_assert_not_reached ("AddMatch message failed");
-
- baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
+
+ baz = dbus_connection_open_private (TEST_CONNECTION, &error);
if (baz == NULL)
_dbus_assert_not_reached ("could not alloc connection");
if (!bus_setup_debug_client (baz))
_dbus_assert_not_reached ("could not set up connection");
+ spin_connection_until_authenticated (context, baz);
+
if (!check_hello_message (context, baz))
_dbus_assert_not_reached ("hello message failed");
if (!check_add_match_all (context, baz))
_dbus_assert_not_reached ("AddMatch message failed");
-
+
+#ifdef DBUS_WIN_FIXME
+ _dbus_warn("TODO: testing of GetConnectionUnixUser message skipped for now\n");
+ _dbus_warn("TODO: testing of GetConnectionUnixProcessID message skipped for now\n");
+#else
+ if (!check_get_connection_unix_user (context, baz))
+ _dbus_assert_not_reached ("GetConnectionUnixUser message failed");
+
+ if (!check_get_connection_unix_process_id (context, baz))
+ _dbus_assert_not_reached ("GetConnectionUnixProcessID message failed");
+#endif
+
+ if (!check_list_services (context, baz))
+ _dbus_assert_not_reached ("ListActivatableNames message failed");
+
if (!check_no_leftovers (context))
{
- _dbus_warn ("Messages were left over after setting up initial connections");
+ _dbus_warn ("Messages were left over after setting up initial connections\n");
_dbus_assert_not_reached ("initial connection setup failed");
}
-
+
check1_try_iterations (context, "create_and_hello",
check_hello_connection);
-
- check2_try_iterations (context, foo, "nonexistent_service_activation",
- check_nonexistent_service_activation);
-
- check2_try_iterations (context, foo, "segfault_service_activation",
- check_segfault_service_activation);
-
- check2_try_iterations (context, foo, "existent_service_activation",
- check_existent_service_activation);
-
+
+ check2_try_iterations (context, foo, "nonexistent_service_no_auto_start",
+ check_nonexistent_service_no_auto_start);
+
+#ifdef DBUS_WIN_FIXME
+ _dbus_warn("TODO: dispatch.c segfault_service_no_auto_start test\n");
+#else
+ check2_try_iterations (context, foo, "segfault_service_no_auto_start",
+ check_segfault_service_no_auto_start);
+#endif
+
+ check2_try_iterations (context, foo, "existent_service_no_auto_start",
+ check_existent_service_no_auto_start);
+
+ check2_try_iterations (context, foo, "nonexistent_service_auto_start",
+ check_nonexistent_service_auto_start);
+
+
+#ifdef DBUS_WIN_FIXME
+ _dbus_warn("TODO: dispatch.c segfault_service_auto_start test\n");
+#else
+ /* only do the segfault test if we are not using the launcher */
+ check2_try_iterations (context, foo, "segfault_service_auto_start",
+ check_segfault_service_auto_start);
+#endif
+
+ /* only do the shell fail test if we are not using the launcher */
+ check2_try_iterations (context, foo, "shell_fail_service_auto_start",
+ check_shell_fail_service_auto_start);
+
+ /* specific to launcher */
+ if (use_launcher)
+ if (!check_launch_service_file_missing (context, foo))
+ _dbus_assert_not_reached ("did not get service file not found error");
+
+#if 0
+ /* Note: need to resolve some issues with the testing code in order to run
+ * this in oom (handle that we sometimes don't get replies back from the bus
+ * when oom happens, without blocking the test).
+ */
+ check2_try_iterations (context, foo, "existent_service_auto_auto_start",
+ check_existent_service_auto_start);
+#endif
+
+ if (!check_existent_service_auto_start (context, foo))
+ _dbus_assert_not_reached ("existent service auto start failed");
+
+ if (!check_shell_service_success_auto_start (context, foo))
+ _dbus_assert_not_reached ("shell success service auto start failed");
+
_dbus_verbose ("Disconnecting foo, bar, and baz\n");
kill_client_connection_unchecked (foo);
kill_client_connection_unchecked (baz);
bus_context_unref (context);
-
+
+ return TRUE;
+}
+
+static dbus_bool_t
+bus_dispatch_test_conf_fail (const DBusString *test_data_dir,
+ const char *filename)
+{
+ BusContext *context;
+ DBusConnection *foo;
+ DBusError error;
+
+ /* save the config name for the activation helper */
+ if (!setenv_TEST_LAUNCH_HELPER_CONFIG (test_data_dir, filename))
+ _dbus_assert_not_reached ("no memory setting TEST_LAUNCH_HELPER_CONFIG");
+
+ dbus_error_init (&error);
+
+ context = bus_context_new_test (test_data_dir, filename);
+ if (context == NULL)
+ return FALSE;
+
+ foo = dbus_connection_open_private (TEST_CONNECTION, &error);
+ if (foo == NULL)
+ _dbus_assert_not_reached ("could not alloc connection");
+
+ if (!bus_setup_debug_client (foo))
+ _dbus_assert_not_reached ("could not set up connection");
+
+ spin_connection_until_authenticated (context, foo);
+
+ if (!check_hello_message (context, foo))
+ _dbus_assert_not_reached ("hello message failed");
+
+ if (!check_double_hello_message (context, foo))
+ _dbus_assert_not_reached ("double hello message failed");
+
+ if (!check_add_match_all (context, foo))
+ _dbus_assert_not_reached ("AddMatch message failed");
+
+ /* this only tests the activation.c user check */
+ if (!check_launch_service_user_missing (context, foo))
+ _dbus_assert_not_reached ("user missing did not trigger error");
+
+ /* this only tests the desktop.c exec check */
+ if (!check_launch_service_exec_missing (context, foo))
+ _dbus_assert_not_reached ("exec missing did not trigger error");
+
+ /* this only tests the desktop.c service check */
+ if (!check_launch_service_service_missing (context, foo))
+ _dbus_assert_not_reached ("service missing did not trigger error");
+
+ _dbus_verbose ("Disconnecting foo\n");
+
+ kill_client_connection_unchecked (foo);
+
+ bus_context_unref (context);
+
+ return TRUE;
+}
+
+dbus_bool_t
+bus_dispatch_test (const DBusString *test_data_dir)
+{
+ /* run normal activation tests */
+ _dbus_verbose ("Normal activation tests\n");
+ if (!bus_dispatch_test_conf (test_data_dir,
+ "valid-config-files/debug-allow-all.conf", FALSE))
+ return FALSE;
+
+#ifdef DBUS_WIN
+ _dbus_warn("Info: Launch helper activation tests skipped because launch-helper is not supported yet\n");
+#else
+ /* run launch-helper activation tests */
+ _dbus_verbose ("Launch helper activation tests\n");
+ if (!bus_dispatch_test_conf (test_data_dir,
+ "valid-config-files-system/debug-allow-all-pass.conf", TRUE))
+ return FALSE;
+
+ /* run select launch-helper activation tests on broken service files */
+ if (!bus_dispatch_test_conf_fail (test_data_dir,
+ "valid-config-files-system/debug-allow-all-fail.conf"))
+ return FALSE;
+#endif
+
return TRUE;
}
DBusError error;
dbus_error_init (&error);
-
+
/* Test SHA1 authentication */
_dbus_verbose ("Testing SHA1 context\n");
-
+
context = bus_context_new_test (test_data_dir,
"valid-config-files/debug-allow-all-sha1.conf");
if (context == NULL)
return FALSE;
- foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
+ foo = dbus_connection_open_private (TEST_CONNECTION, &error);
if (foo == NULL)
_dbus_assert_not_reached ("could not alloc connection");
if (!bus_setup_debug_client (foo))
_dbus_assert_not_reached ("could not set up connection");
+ spin_connection_until_authenticated (context, foo);
+
if (!check_hello_message (context, foo))
_dbus_assert_not_reached ("hello message failed");
if (!check_add_match_all (context, foo))
_dbus_assert_not_reached ("addmatch message failed");
-
+
if (!check_no_leftovers (context))
{
_dbus_warn ("Messages were left over after setting up initial SHA-1 connection\n");
_dbus_assert_not_reached ("initial connection setup failed");
}
-
+
check1_try_iterations (context, "create_and_hello_sha1",
check_hello_connection);
return TRUE;
}
+#ifdef HAVE_UNIX_FD_PASSING
+
+dbus_bool_t
+bus_unix_fds_passing_test(const DBusString *test_data_dir)
+{
+ BusContext *context;
+ DBusConnection *foo, *bar;
+ DBusError error;
+ DBusMessage *m;
+ dbus_bool_t b;
+ int one[2], two[2], x, y, z;
+ char r;
+
+ dbus_error_init (&error);
+
+ context = bus_context_new_test (test_data_dir, "valid-config-files/debug-allow-all.conf");
+ if (context == NULL)
+ _dbus_assert_not_reached ("could not alloc context");
+
+ foo = dbus_connection_open_private (TEST_CONNECTION, &error);
+ if (foo == NULL)
+ _dbus_assert_not_reached ("could not alloc connection");
+
+ if (!bus_setup_debug_client (foo))
+ _dbus_assert_not_reached ("could not set up connection");
+
+ spin_connection_until_authenticated (context, foo);
+
+ if (!check_hello_message (context, foo))
+ _dbus_assert_not_reached ("hello message failed");
+
+ if (!check_add_match_all (context, foo))
+ _dbus_assert_not_reached ("AddMatch message failed");
+
+ bar = dbus_connection_open_private (TEST_CONNECTION, &error);
+ if (bar == NULL)
+ _dbus_assert_not_reached ("could not alloc connection");
+
+ if (!bus_setup_debug_client (bar))
+ _dbus_assert_not_reached ("could not set up connection");
+
+ spin_connection_until_authenticated (context, bar);
+
+ if (!check_hello_message (context, bar))
+ _dbus_assert_not_reached ("hello message failed");
+
+ if (!check_add_match_all (context, bar))
+ _dbus_assert_not_reached ("AddMatch message failed");
+
+ if (!(m = dbus_message_new_signal("/", "a.b.c", "d")))
+ _dbus_assert_not_reached ("could not alloc message");
+
+ if (!(_dbus_full_duplex_pipe(one, one+1, TRUE, &error)))
+ _dbus_assert_not_reached("Failed to allocate pipe #1");
+
+ if (!(_dbus_full_duplex_pipe(two, two+1, TRUE, &error)))
+ _dbus_assert_not_reached("Failed to allocate pipe #2");
+
+ if (!dbus_message_append_args(m,
+ DBUS_TYPE_UNIX_FD, one,
+ DBUS_TYPE_UNIX_FD, two,
+ DBUS_TYPE_UNIX_FD, two,
+ DBUS_TYPE_INVALID))
+ _dbus_assert_not_reached("Failed to attach fds.");
+
+ if (!_dbus_close(one[0], &error))
+ _dbus_assert_not_reached("Failed to close pipe #1 ");
+ if (!_dbus_close(two[0], &error))
+ _dbus_assert_not_reached("Failed to close pipe #2 ");
+
+ if (!(dbus_connection_can_send_type(foo, DBUS_TYPE_UNIX_FD)))
+ _dbus_assert_not_reached("Connection cannot do fd passing");
+
+ if (!(dbus_connection_can_send_type(bar, DBUS_TYPE_UNIX_FD)))
+ _dbus_assert_not_reached("Connection cannot do fd passing");
+
+ if (!dbus_connection_send (foo, m, NULL))
+ _dbus_assert_not_reached("Failed to send fds");
+
+ dbus_message_unref(m);
+
+ bus_test_run_clients_loop (SEND_PENDING (foo));
+
+ bus_test_run_everything (context);
+
+ block_connection_until_message_from_bus (context, foo, "unix fd reception on foo");
+
+ if (!(m = pop_message_waiting_for_memory (foo)))
+ _dbus_assert_not_reached("Failed to receive msg");
+
+ if (!dbus_message_is_signal(m, "a.b.c", "d"))
+ _dbus_assert_not_reached("bogus message received");
+
+ dbus_message_unref(m);
+
+ block_connection_until_message_from_bus (context, bar, "unix fd reception on bar");
+
+ if (!(m = pop_message_waiting_for_memory (bar)))
+ _dbus_assert_not_reached("Failed to receive msg");
+
+ if (!dbus_message_is_signal(m, "a.b.c", "d"))
+ _dbus_assert_not_reached("bogus message received");
+
+ if (!dbus_message_get_args(m,
+ &error,
+ DBUS_TYPE_UNIX_FD, &x,
+ DBUS_TYPE_UNIX_FD, &y,
+ DBUS_TYPE_UNIX_FD, &z,
+ DBUS_TYPE_INVALID))
+ _dbus_assert_not_reached("Failed to parse fds.");
+
+ dbus_message_unref(m);
+
+ if (write(x, "X", 1) != 1)
+ _dbus_assert_not_reached("Failed to write to pipe #1");
+ if (write(y, "Y", 1) != 1)
+ _dbus_assert_not_reached("Failed to write to pipe #2");
+ if (write(z, "Z", 1) != 1)
+ _dbus_assert_not_reached("Failed to write to pipe #2/2nd fd");
+
+ if (!_dbus_close(x, &error))
+ _dbus_assert_not_reached("Failed to close pipe #1/other side ");
+ if (!_dbus_close(y, &error))
+ _dbus_assert_not_reached("Failed to close pipe #2/other side ");
+ if (!_dbus_close(z, &error))
+ _dbus_assert_not_reached("Failed to close pipe #2/other size 2nd fd ");
+
+ if (read(one[1], &r, 1) != 1 || r != 'X')
+ _dbus_assert_not_reached("Failed to read value from pipe.");
+ if (read(two[1], &r, 1) != 1 || r != 'Y')
+ _dbus_assert_not_reached("Failed to read value from pipe.");
+ if (read(two[1], &r, 1) != 1 || r != 'Z')
+ _dbus_assert_not_reached("Failed to read value from pipe.");
+
+ if (!_dbus_close(one[1], &error))
+ _dbus_assert_not_reached("Failed to close pipe #1 ");
+ if (!_dbus_close(two[1], &error))
+ _dbus_assert_not_reached("Failed to close pipe #2 ");
+
+ _dbus_verbose ("Disconnecting foo\n");
+ kill_client_connection_unchecked (foo);
+
+ _dbus_verbose ("Disconnecting bar\n");
+ kill_client_connection_unchecked (bar);
+
+ bus_context_unref (context);
+
+ return TRUE;
+}
+#endif
+
#endif /* DBUS_BUILD_TESTS */