+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
+
+ 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",
+ "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 (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;
+ }
+ }
+ }
+
+ 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_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 = 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, &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;
+
+ 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: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
+
+ 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",
+ "GetConnectionUnixProcessID", 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 */
+ }
+#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 */
+ }
+ else
+ {
+ warn_unexpected (connection, message,
+ "method_return for GetConnectionUnixProcessID");
+
+ goto out;
+ }
+
+ retry_get_property:
+
+ if (!dbus_message_get_args (message, &error,
+ 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 retry_get_property;
+ }
+ else
+ {
+ _dbus_assert (dbus_error_is_set (&error));
+ _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixProcessID\n");
+ goto out;
+ }
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+#endif /* !DBUS_WIN */
+ }
+
+ 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_add_match_all (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_bool_t retval;
+ dbus_uint32_t serial;
+ DBusError error;
+ const char *empty = "";
+
+ 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_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "AddMatch");
+
+ if (message == NULL)
+ return TRUE;
+
+ /* 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: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
+
+ 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: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
+
+ 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: %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",
+ "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: %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))
+ {
+ ; /* 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);
+ 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: %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 %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: %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",
+ "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: %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_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: %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, 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: %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("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);
+ 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: %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_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: %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 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\n");
+ goto out;
+ }
+
+ /* 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 ("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)\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;
+ }
+
+ 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;
+ }
+
+ if (strcmp("--what", argv[5]) != 0)
+ {
+ _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)\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;
+}
+
+typedef struct
+{
+ Check1Func func;
+ BusContext *context;
+} Check1Data;
+
+static dbus_bool_t
+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 **srvs;
+ int l;
+
+ retval = FALSE;
+ dbus_error_init (&error);
+ 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_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 ListActivatableNames/ListNames");
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
+
+ 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",
+ method, 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 (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ {
+ ; /* good, expected */
+ }
+ else
+ {
+ warn_unexpected (connection, message,
+ "method_return for ListActivatableNames/ListNames");
+
+ goto out;
+ }
+
+ retry_get_property:
+
+ 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);
+
+ return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_list_services (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;
+ 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, &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: %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 %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:
+ 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))
+ {
+ 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;
+ }
+
+ dbus_free_string_array (services);
+
+ 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;
+}
+
+typedef struct
+{
+ Check2Func func;
+ BusContext *context;
+ DBusConnection *connection;
+} Check2Data;
+
+static dbus_bool_t
+check_oom_check2_func (void *data)
+{
+ Check2Data *d = data;
+
+ 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\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+check2_try_iterations (BusContext *context,
+ DBusConnection *connection,
+ const char *description,
+ Check2Func func)
+{
+ Check2Data d;
+
+ d.func = func;
+ d.context = context;
+ d.connection = connection;
+
+ if (!_dbus_test_oom_handling (description, check_oom_check2_func,
+ &d))
+ {
+ _dbus_warn ("%s failed during oom\n", description);
+ _dbus_assert_not_reached ("test failed");
+ }
+}
+
+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 *bar;
+ 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, 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");
+
+ 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_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\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_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 (bar);
+ 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);