-/* -*- 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
*
* 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 <dbus/dbus-internals.h>
#include <string.h>
+#ifdef HAVE_UNIX_FD_PASSING
+#include <dbus/dbus-sysdeps-unix.h>
+#include <unistd.h>
+#endif
+
+#ifdef DBUS_UNIX
+#define TEST_CONNECTION "debug-pipe:name=test-server"
+#else
+#define TEST_CONNECTION "tcp:host=localhost,port=1234"
+#endif
+
static dbus_bool_t
send_one_message (DBusConnection *connection,
BusContext *context,
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,
_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;
{
addressed_recipient = bus_service_get_primary_owners_connection (service);
_dbus_assert (addressed_recipient != NULL);
-
- if (!bus_context_check_security_policy (context, transaction,
- 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;
|| (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");
+ _dbus_warn ("inconsistent NameOwnerChanged arguments\n");
goto out;
}
{
; /* good, this is a valid response */
}
+#ifdef DBUS_WIN
+ else if (dbus_message_is_error (message, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN))
+ {
+ /* 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
{
+#ifdef DBUS_WIN
+ warn_unexpected (connection, message, "GetConnectionUnixProcessID to fail on Windows");
+ goto out;
+#else
if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
{
; /* good, expected */
_dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixProcessID\n");
goto out;
}
- } else {
-
+ }
+ else
+ {
/* test if returned pid is the same as our own pid
*
* @todo It would probably be good to restructure the tests
goto out;
}
}
+#endif /* !DBUS_WIN */
}
if (!check_no_leftovers (context))
dbus_error_init (&error);
- connection = dbus_connection_open_private ("debug-pipe:name=test-server", &error);
+ connection = dbus_connection_open_private (TEST_CONNECTION, &error);
if (connection == NULL)
{
_DBUS_ASSERT_ERROR_IS_SET (&error);
}
else
{
- _dbus_warn ("unexpected arguments for NameOwnerChanged message");
+ _dbus_warn ("unexpected arguments for NameOwnerChanged message\n");
message_kind = GOT_SOMETHING_ELSE;
}
}
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;
}
return retval;
}
+#ifndef DBUS_WIN_FIXME
/* returns TRUE if the correct thing happens,
* but the correct thing may include OOM errors.
*/
; /* 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 */
return retval;
}
+#endif
#define TEST_ECHO_MESSAGE "Test echo message"
#define TEST_RUN_HELLO_FROM_SELF_MESSAGE "Test sending message to self"
if (message == NULL)
{
_dbus_warn ("No message after auto activation "
- "(should be a service announcement)");
+ "(should be a service announcement)\n");
dbus_connection_return_message (connection, message);
message = NULL;
goto out;
return retval;
}
-#define SHELL_FAIL_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceFail"
+#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_shell_fail_service_auto_start (BusContext *context,
- DBusConnection *connection)
+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 (SHELL_FAIL_SERVICE_NAME,
+ 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);
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");
+ 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))
; /* good, this is a valid response */
}
else if (dbus_message_is_error (message,
- DBUS_ERROR_INVALID_ARGS))
+ DBUS_ERROR_SERVICE_UNKNOWN))
{
- _dbus_verbose("got invalid args\n");
- ; /* good, this is expected also */
+ _dbus_verbose("got service unknown\n");
+ ; /* good, this is expected (only valid when using launch helper) */
}
else
{
}
else
{
- _dbus_warn ("Did not expect to successfully auto-start shell fail service\n");
+ _dbus_warn ("Did not expect to successfully auto-start missing service\n");
goto out;
}
return retval;
}
-#define SHELL_SUCCESS_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess"
+#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_shell_service_success_auto_start (BusContext *context,
- DBusConnection *connection)
+check_launch_service_user_missing (BusContext *context,
+ DBusConnection *connection)
{
DBusMessage *message;
- DBusMessage *base_service_message;
dbus_uint32_t serial;
dbus_bool_t retval;
- const char *base_service;
- const char *argv[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
- base_service_message = NULL;
-
- message = dbus_message_new_method_call (SHELL_SUCCESS_SERVICE_NAME,
+ message = dbus_message_new_method_call (SERVICE_USER_MISSING_NAME,
"/org/freedesktop/TestSuite",
"org.freedesktop.TestSuite",
"Echo");
-
+
if (message == NULL)
return TRUE;
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 shell success service");
+ 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_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
+ _dbus_warn ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
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);
+ _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);
- _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)
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
{
- 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)
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("No message after auto activation "
- "(should be a service announcement)");
- dbus_connection_return_message (connection, message);
- message = NULL;
+ _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");
- message_kind = check_got_service_info (message);
-
- dbus_connection_return_message (connection, message);
- message = NULL;
+ goto out;
+ }
+ }
+ else
+ {
+ _dbus_warn ("Did not expect to successfully auto-start missing service\n");
+ goto out;
+ }
- 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;
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
- break;
+#define SERVICE_EXEC_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoExec"
- 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);
+/* 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;
- if (socd.failed)
- goto out;
+ message = dbus_message_new_method_call (SERVICE_EXEC_MISSING_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Echo");
- break;
- }
+ if (message == NULL)
+ return TRUE;
- case GOT_ERROR:
- case GOT_SOMETHING_ELSE:
- _dbus_warn ("Unexpected message after auto activation\n");
- goto out;
- }
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
}
- /* OK, now we've dealt with ServiceOwnerChanged signals, now should
- * come the method reply (or error) from the initial method call
- */
+ dbus_message_unref (message);
+ message = NULL;
- /* 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");
-
+ 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: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
+ return TRUE;
+ }
+
+ retval = FALSE;
+
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "Echo message (auto activation)", serial, connection);
goto out;
}
- if (dbus_message_get_reply_serial (message) != serial)
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
{
- _dbus_warn ("Wrong reply serial\n");
+ 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
+ {
+ _dbus_warn ("Did not expect to successfully auto-start missing service\n");
goto out;
}
- if (!dbus_message_get_args (message, NULL,
- DBUS_TYPE_STRING, &argv[0],
- DBUS_TYPE_STRING, &argv[1],
- DBUS_TYPE_STRING, &argv[2],
+ 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;
+ }
+
+ 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))
+ {
+ _dbus_warn ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
+ 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
+ {
+ _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_shell_fail_service_auto_start (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+
+ 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: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
+ 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_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 ("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_shell_service_success_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 *argv[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+
+ base_service_message = NULL;
+
+ message = dbus_message_new_method_call (SHELL_SUCCESS_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);
+
+ /* 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);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
+ 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, 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;
+ }
+ }
+
+ /* 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;
+ }
+
+ 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");
+ _dbus_warn ("Error getting arguments from return\n");
goto out;
}
*/
if (strcmp("-test", argv[1]) != 0)
{
- _dbus_warn ("Unexpected argv[1] in shell success service test (expected: %s, got: %s)",
+ _dbus_warn ("Unexpected argv[1] in shell success service test (expected: %s, got: %s)\n",
"-test", argv[1]);
goto out;
}
if (strcmp("that", argv[2]) != 0)
{
- _dbus_warn ("Unexpected argv[2] in shell success service test (expected: %s, got: %s)",
+ _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)",
+ _dbus_warn ("Unexpected argv[3] in shell success service test (expected: %s, got: %s)\n",
"we get", argv[3]);
goto out;
}
if (strcmp("back", argv[4]) != 0)
{
- _dbus_warn ("Unexpected argv[4] in shell success service test (expected: %s, got: %s)",
+ _dbus_warn ("Unexpected argv[4] in shell success service test (expected: %s, got: %s)\n",
"back", argv[4]);
goto out;
}
if (strcmp("--what", argv[5]) != 0)
{
- _dbus_warn ("Unexpected argv[5] in shell success service test (expected: %s, got: %s)",
+ _dbus_warn ("Unexpected argv[5] in shell success service test (expected: %s, got: %s)\n",
"--what", argv[5]);
goto out;
}
if (strcmp("we put in", argv[6]) != 0)
{
- _dbus_warn ("Unexpected argv[6] in shell success service test (expected: %s, got: %s)",
+ _dbus_warn ("Unexpected argv[6] in shell success service test (expected: %s, got: %s)\n",
"we put in", argv[6]);
goto out;
}
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;
}
case GOT_ERROR:
case GOT_SERVICE_DELETED:
_dbus_warn ("Unexpected message after ActivateService "
- "(should be an error or a service announcement");
+ "(should be an error or a service announcement)\n");
goto out;
case GOT_SERVICE_CREATED:
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;
}
}
}
-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_private ("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 (!check_add_match_all (context, foo))
_dbus_assert_not_reached ("AddMatch message failed");
- bar = dbus_connection_open_private ("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 (!check_add_match_all (context, bar))
_dbus_assert_not_reached ("AddMatch message failed");
- baz = dbus_connection_open_private ("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 (!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");
}
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
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;
+
+ /* 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;
+
+ return TRUE;
+}
+
dbus_bool_t
bus_dispatch_sha1_test (const DBusString *test_data_dir)
{
if (context == NULL)
return FALSE;
- foo = dbus_connection_open_private ("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");
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 */