-/* -*- mode: C; c-file-style: "gnu" -*- */
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* test.c unit test routines
*
* Copyright (C) 2003 Red Hat, Inc.
*
- * Licensed under the Academic Free License version 1.2
- *
+ * Licensed under the Academic Free License version 2.1
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <config.h>
-#ifdef DBUS_BUILD_TESTS
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
#include "test.h"
-#include "loop.h"
#include <dbus/dbus-internals.h>
#include <dbus/dbus-list.h>
+#include <dbus/dbus-sysdeps.h>
/* The "debug client" watch/timeout handlers don't dispatch messages,
* as we manually pull them in order to verify them. This is why they
* are different from the real handlers in connection.c
*/
static DBusList *clients = NULL;
-
-static dbus_bool_t
-client_watch_callback (DBusWatch *watch,
- unsigned int condition,
- void *data)
-{
- DBusConnection *connection = data;
- dbus_bool_t retval;
-
- dbus_connection_ref (connection);
-
- retval = dbus_connection_handle_watch (connection, watch, condition);
-
- dbus_connection_unref (connection);
-
- return retval;
-}
+static DBusLoop *client_loop = NULL;
static dbus_bool_t
add_client_watch (DBusWatch *watch,
- DBusConnection *connection)
+ void *data)
{
- return bus_loop_add_watch (watch, client_watch_callback, connection,
- NULL);
+ return _dbus_loop_add_watch (client_loop, watch);
}
static void
remove_client_watch (DBusWatch *watch,
- DBusConnection *connection)
+ void *data)
{
- bus_loop_remove_watch (watch, client_watch_callback, connection);
+ _dbus_loop_remove_watch (client_loop, watch);
}
static void
-client_timeout_callback (DBusTimeout *timeout,
- void *data)
+toggle_client_watch (DBusWatch *watch,
+ void *data)
{
- DBusConnection *connection = data;
-
- dbus_connection_ref (connection);
-
- /* can return FALSE on OOM but we just let it fire again later */
- dbus_timeout_handle (timeout);
-
- dbus_connection_unref (connection);
+ _dbus_loop_toggle_watch (client_loop, watch);
}
static dbus_bool_t
add_client_timeout (DBusTimeout *timeout,
- DBusConnection *connection)
+ void *data)
{
- return bus_loop_add_timeout (timeout, client_timeout_callback, connection, NULL);
+ return _dbus_loop_add_timeout (client_loop, timeout);
}
static void
remove_client_timeout (DBusTimeout *timeout,
- DBusConnection *connection)
+ void *data)
{
- bus_loop_remove_timeout (timeout, client_timeout_callback, connection);
+ _dbus_loop_remove_timeout (client_loop, timeout);
}
static DBusHandlerResult
-client_disconnect_handler (DBusMessageHandler *handler,
- DBusConnection *connection,
- DBusMessage *message,
- void *user_data)
+client_disconnect_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
{
+ if (!dbus_message_is_signal (message,
+ DBUS_INTERFACE_LOCAL,
+ "Disconnected"))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
_dbus_verbose ("Removing client %p in disconnect handler\n",
connection);
-
- _dbus_list_remove (&clients, connection);
-
- dbus_connection_unref (connection);
-
- return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-}
-
-static int handler_slot = -1;
-static int handler_slot_refcount = 0;
-
-static dbus_bool_t
-handler_slot_ref (void)
-{
- if (handler_slot < 0)
- {
- handler_slot = dbus_connection_allocate_data_slot ();
-
- if (handler_slot < 0)
- return FALSE;
- _dbus_assert (handler_slot_refcount == 0);
- }
-
- handler_slot_refcount += 1;
-
- return TRUE;
-
-}
+ _dbus_list_remove (&clients, connection);
-static void
-handler_slot_unref (void)
-{
- _dbus_assert (handler_slot_refcount > 0);
+ dbus_connection_unref (connection);
- handler_slot_refcount -= 1;
-
- if (handler_slot_refcount == 0)
+ if (clients == NULL)
{
- dbus_connection_free_data_slot (handler_slot);
- handler_slot = -1;
+ _dbus_loop_unref (client_loop);
+ client_loop = NULL;
}
-}
-
-static void
-free_handler (void *data)
-{
- DBusMessageHandler *handler = data;
- dbus_message_handler_unref (handler);
- handler_slot_unref ();
+ return DBUS_HANDLER_RESULT_HANDLED;
}
dbus_bool_t
bus_setup_debug_client (DBusConnection *connection)
{
- DBusMessageHandler *disconnect_handler;
- const char *to_handle[] = { DBUS_MESSAGE_LOCAL_DISCONNECT };
dbus_bool_t retval;
-
- disconnect_handler = dbus_message_handler_new (client_disconnect_handler,
- NULL, NULL);
- if (disconnect_handler == NULL)
+ if (!dbus_connection_add_filter (connection,
+ client_disconnect_filter,
+ NULL, NULL))
return FALSE;
- if (!dbus_connection_register_handler (connection,
- disconnect_handler,
- to_handle,
- _DBUS_N_ELEMENTS (to_handle)))
+ retval = FALSE;
+
+ if (client_loop == NULL)
{
- dbus_message_handler_unref (disconnect_handler);
- return FALSE;
+ client_loop = _dbus_loop_new ();
+ if (client_loop == NULL)
+ goto out;
}
- retval = FALSE;
-
if (!dbus_connection_set_watch_functions (connection,
- (DBusAddWatchFunction) add_client_watch,
- (DBusRemoveWatchFunction) remove_client_watch,
- NULL,
+ add_client_watch,
+ remove_client_watch,
+ toggle_client_watch,
connection,
NULL))
goto out;
-
+
if (!dbus_connection_set_timeout_functions (connection,
- (DBusAddTimeoutFunction) add_client_timeout,
- (DBusRemoveTimeoutFunction) remove_client_timeout,
+ add_client_timeout,
+ remove_client_timeout,
NULL,
connection, NULL))
goto out;
if (!_dbus_list_append (&clients, connection))
goto out;
- if (!handler_slot_ref ())
- goto out;
-
- /* Set up handler to be destroyed */
- if (!dbus_connection_set_data (connection, handler_slot,
- disconnect_handler,
- free_handler))
- {
- handler_slot_unref ();
- goto out;
- }
-
retval = TRUE;
-
+
out:
if (!retval)
{
- dbus_message_handler_unref (disconnect_handler); /* unregisters it */
-
+ dbus_connection_remove_filter (connection,
+ client_disconnect_filter,
+ NULL);
+
dbus_connection_set_watch_functions (connection,
NULL, NULL, NULL, NULL, NULL);
dbus_connection_set_timeout_functions (connection,
NULL, NULL, NULL, NULL, NULL);
_dbus_list_remove_last (&clients, connection);
+
+ if (clients == NULL)
+ {
+ _dbus_loop_unref (client_loop);
+ client_loop = NULL;
+ }
}
-
+
return retval;
}
void *data)
{
DBusList *link;
-
+
link = _dbus_list_get_first_link (&clients);
while (link != NULL)
{
if (!(* function) (connection, data))
break;
-
+
link = next;
}
}
bus_test_client_listed (DBusConnection *connection)
{
DBusList *link;
-
+
link = _dbus_list_get_first_link (&clients);
while (link != NULL)
{
if (c == connection)
return TRUE;
-
+
link = next;
}
return FALSE;
}
+void
+bus_test_run_clients_loop (dbus_bool_t block_once)
+{
+ if (client_loop == NULL)
+ return;
+
+ _dbus_verbose ("---> Dispatching on \"client side\"\n");
+
+ /* dispatch before we block so pending dispatches
+ * won't make our block return early
+ */
+ _dbus_loop_dispatch (client_loop);
+
+ /* Do one blocking wait, since we're expecting data */
+ if (block_once)
+ {
+ _dbus_verbose ("---> blocking on \"client side\"\n");
+ _dbus_loop_iterate (client_loop, TRUE);
+ }
+
+ /* Then mop everything up */
+ while (_dbus_loop_iterate (client_loop, FALSE))
+ ;
+
+ _dbus_verbose ("---> Done dispatching on \"client side\"\n");
+}
void
-bus_test_flush_bus (BusContext *context)
+bus_test_run_bus_loop (BusContext *context,
+ dbus_bool_t block_once)
{
- /* This is race condition city, obviously. since we're all in one
- * process we can't block, we just have to wait for data we put in
- * one end of the debug pipe to come out the other end...
- * a more robust setup would be good. Blocking on the other
- * end of pipes we've pushed data into or something.
+ _dbus_verbose ("---> Dispatching on \"server side\"\n");
+
+ /* dispatch before we block so pending dispatches
+ * won't make our block return early
*/
-
- while (bus_loop_iterate (FALSE))
+ _dbus_loop_dispatch (bus_context_get_loop (context));
+
+ /* Do one blocking wait, since we're expecting data */
+ if (block_once)
+ {
+ _dbus_verbose ("---> blocking on \"server side\"\n");
+ _dbus_loop_iterate (bus_context_get_loop (context), TRUE);
+ }
+
+ /* Then mop everything up */
+ while (_dbus_loop_iterate (bus_context_get_loop (context), FALSE))
;
- _dbus_sleep_milliseconds (15);
- while (bus_loop_iterate (FALSE))
+
+ _dbus_verbose ("---> Done dispatching on \"server side\"\n");
+}
+
+void
+bus_test_run_everything (BusContext *context)
+{
+ while (_dbus_loop_iterate (bus_context_get_loop (context), FALSE) ||
+ (client_loop == NULL || _dbus_loop_iterate (client_loop, FALSE)))
;
}
+BusContext*
+bus_context_new_test (const DBusString *test_data_dir,
+ const char *filename)
+{
+ DBusError error;
+ DBusString config_file;
+ DBusString relative;
+ BusContext *context;
+
+ if (!_dbus_string_init (&config_file))
+ {
+ _dbus_warn ("No memory\n");
+ return NULL;
+ }
+
+ if (!_dbus_string_copy (test_data_dir, 0,
+ &config_file, 0))
+ {
+ _dbus_warn ("No memory\n");
+ _dbus_string_free (&config_file);
+ return NULL;
+ }
+
+ _dbus_string_init_const (&relative, filename);
+
+ if (!_dbus_concat_dir_and_file (&config_file, &relative))
+ {
+ _dbus_warn ("No memory\n");
+ _dbus_string_free (&config_file);
+ return NULL;
+ }
+
+ dbus_error_init (&error);
+ context = bus_context_new (&config_file, BUS_CONTEXT_FLAG_NONE, NULL, NULL, NULL, &error);
+ if (context == NULL)
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (&error);
+
+ _dbus_warn ("Failed to create debug bus context from configuration file %s: %s\n",
+ filename, error.message);
+
+ dbus_error_free (&error);
+
+ _dbus_string_free (&config_file);
+
+ return NULL;
+ }
+
+ _dbus_string_free (&config_file);
+
+ return context;
+}
+
#endif