diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c
index 5b1feb90..508057e2 100644
--- a/dbus/dbus-sysdeps-win.c
+++ b/dbus/dbus-sysdeps-win.c
@@ -2895,6 +2895,44 @@ static const char *cDBusDaemonMutex = "DBusDaemonMutex";
// named shm for dbus adress info (per user)
static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo";
+/* custom command line parameter for autolaunching daemon */
+static const char *autolaunch_custom_command_line_parameter = "";
+
+/**
+ * Set command line parameters for the dbus daemon to start
+ * for an autolaunch session.
+ *
+ * The specified instance must be valid until the dbus-daemon
+ * is started.
+ *
+ * This function is not thread-safe, and can only be called from a
+ * single-threaded unit test.
+ *
+ * @param path string to use as command line parameter
+ */
+void _dbus_test_win_autolaunch_set_command_line_parameter (const char *path)
+{
+ autolaunch_custom_command_line_parameter = path;
+}
+
+static HANDLE *autolaunch_handle_location;
+
+/**
+ * Set location where to store process handle of an autostarted server
+ *
+ * This function is not thread-safe, and can only be called from a
+ * single-threaded unit test.
+ *
+ * After using the handle it must be closed with @ref CloseHandle().
+ *
+ * @param location Pointer where to store the handle
+ */
+void
+_dbus_test_win_set_autolaunch_handle_location (HANDLE *location)
+{
+ autolaunch_handle_location = location;
+}
+
/**
* Return the hash of the installation root directory, which can be
* used to construct a per-installation-root scope for autolaunching
@@ -3235,41 +3273,53 @@ _dbus_daemon_unpublish_session_bus_address (void)
return TRUE;
}
+/**
+ * Get server bus address from shared memory segment provided by running dbus-daemon
+ *
+ * @param address initialized DBusString instance to store the retrieved address
+ * @param shm_name the name of the shared memory segment
+ * @param wait if TRUE wait maximum 2 seconds for the presence of the shared memory segment
+ * @return #TRUE the bus address was fetched from the shared memory segment
+ * @return #FALSE error during execution
+ */
static dbus_bool_t
-_dbus_get_autolaunch_shm (DBusString *address, DBusString *shm_name)
+_dbus_get_autolaunch_shm (DBusString *address, DBusString *shm_name, dbus_bool_t wait)
{
- HANDLE sharedMem;
+ HANDLE sharedMem = NULL;
char *shared_addr;
int i;
+ int max = 20; /* max 2 seconds */
+ dbus_bool_t retval = FALSE;
+
+ if (!wait)
+ max = 1;
// read shm
- for(i=0;i<20;++i) {
+ for (i = 0; i < max; ++i)
+ {
// we know that dbus-daemon is available, so we wait until shm is available
sharedMem = OpenFileMappingA (FILE_MAP_READ, FALSE, _dbus_string_get_const_data (shm_name));
if (sharedMem == 0)
- Sleep (100);
- if ( sharedMem != 0)
- break;
- }
+ Sleep (100);
+ if (sharedMem != 0)
+ break;
+ }
if (sharedMem == 0)
- return FALSE;
+ return FALSE;
shared_addr = MapViewOfFile (sharedMem, FILE_MAP_READ, 0, 0, 0);
if (!shared_addr)
- return FALSE;
+ goto out;
- _dbus_string_init (address);
+ retval = _dbus_string_append (address, shared_addr);
- _dbus_string_append (address, shared_addr);
-
- // cleanup
UnmapViewOfFile (shared_addr);
+out:
CloseHandle (sharedMem);
-
- return TRUE;
+ return retval;
}
static dbus_bool_t
@@ -3283,7 +3333,7 @@ _dbus_daemon_already_runs (DBusString *address, DBusString *shm_name, const char
if (!_dbus_string_init (&mutex_name))
return FALSE;
- if (!_dbus_get_mutex_name (&mutex_name,scope) ||
+ if (!_dbus_get_mutex_name (&mutex_name, scope) ||
/* not determinable */
_dbus_string_get_length (&mutex_name) == 0)
{
@@ -3300,15 +3350,15 @@ _dbus_daemon_already_runs (DBusString *address, DBusString *shm_name, const char
// do checks
daemon = CreateMutexA (NULL, FALSE, _dbus_string_get_const_data (&mutex_name));
- if(WaitForSingleObject (daemon, 10) != WAIT_TIMEOUT)
+ if (WaitForSingleObject (daemon, 10) != WAIT_TIMEOUT)
{
ReleaseMutex (daemon);
CloseHandle (daemon);
goto out;
}
- // read shm
- retval = _dbus_get_autolaunch_shm (address, shm_name);
+ // read shm, wait max 2 seconds
+ retval = _dbus_get_autolaunch_shm (address, shm_name, TRUE);
// cleanup
CloseHandle (daemon);
@@ -3333,14 +3383,15 @@ _dbus_get_autolaunch_address (const char *scope,
LPSTR lpFile;
char dbus_exe_path[MAX_PATH];
DBusString dbus_args = _DBUS_STRING_INIT_INVALID;
- const char * daemon_name = DBUS_DAEMON_NAME ".exe";
+ const char *daemon_name = DBUS_DAEMON_NAME ".exe";
DBusString shm_name;
+ HANDLE ready_event_handle = NULL;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
if (!_dbus_string_init (&shm_name))
{
- _DBUS_SET_OOM(error);
+ _DBUS_SET_OOM (error);
return FALSE;
}
@@ -3365,12 +3416,12 @@ _dbus_get_autolaunch_address (const char *scope,
if (_dbus_daemon_already_runs (address, &shm_name, scope))
{
_dbus_verbose ("found running dbus daemon for scope '%s' at %s\n",
- scope ? scope : "", _dbus_string_get_const_data (&shm_name) );
+ scope ? scope : "", _dbus_string_get_const_data (&shm_name));
retval = TRUE;
goto out;
}
- if (!SearchPathA (NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile))
+ if (!SearchPathA (NULL, daemon_name, NULL, sizeof (dbus_exe_path), dbus_exe_path, &lpFile))
{
// Look in directory containing dbus shared library
HMODULE hmod;
@@ -3381,7 +3432,7 @@ _dbus_get_autolaunch_address (const char *scope,
"trying path where dbus shared library is located");
hmod = _dbus_win_get_dll_hmodule ();
- rc = GetModuleFileNameA (hmod, dbus_module_path, sizeof(dbus_module_path));
+ rc = GetModuleFileNameA (hmod, dbus_module_path, sizeof (dbus_module_path));
if (rc <= 0)
{
dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not retrieve dbus shared library file name");
@@ -3393,7 +3444,7 @@ _dbus_get_autolaunch_address (const char *scope,
char *ext_idx = strrchr (dbus_module_path, '\\');
if (ext_idx)
*ext_idx = '\0';
- if (!SearchPathA (dbus_module_path, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile))
+ if (!SearchPathA (dbus_module_path, daemon_name, NULL, sizeof (dbus_exe_path), dbus_exe_path, &lpFile))
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"Could not find dbus-daemon executable. "
@@ -3407,11 +3458,10 @@ _dbus_get_autolaunch_address (const char *scope,
}
}
-
// Create process
- ZeroMemory (&si, sizeof(si));
+ ZeroMemory (&si, sizeof (si));
si.cb = sizeof (si);
- ZeroMemory (&pi, sizeof(pi));
+ ZeroMemory (&pi, sizeof (pi));
if (!_dbus_string_init (&dbus_args))
{
@@ -3420,19 +3470,79 @@ _dbus_get_autolaunch_address (const char *scope,
goto out;
}
- if (!_dbus_string_append_printf (&dbus_args, "\"%s\" --session", dbus_exe_path))
+ if (!_dbus_string_append_printf (&dbus_args, "\"%s\" %s", dbus_exe_path,
+ autolaunch_custom_command_line_parameter ? autolaunch_custom_command_line_parameter : "--session"))
{
- dbus_set_error_const (error, DBUS_ERROR_NO_MEMORY, "Failed to append string to argument buffer");
+ _DBUS_SET_OOM (error);
retval = FALSE;
goto out;
}
-// argv[i] = "--config-file=bus\\session.conf";
- if(CreateProcessA (dbus_exe_path, _dbus_string_get_data (&dbus_args), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
+ ready_event_handle = _dbus_win_event_create_inheritable (error);
+ if (ready_event_handle == NULL)
+ goto out;
+
+ _dbus_verbose ("Creating connection readiness event: handle=%p\n", ready_event_handle);
+ if (!_dbus_string_append_printf (&dbus_args, " \"--ready-event-handle=%p\"", ready_event_handle))
{
+ _DBUS_SET_OOM (error);
+ goto out;
+ }
+
+ _dbus_verbose ("Starting dbus daemon with args: '%s'\n", _dbus_string_get_const_data (&dbus_args));
+ if (CreateProcessA (dbus_exe_path, _dbus_string_get_data (&dbus_args), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
+ {
+ DWORD status;
+ HANDLE events[2];
+
CloseHandle (pi.hThread);
- CloseHandle (pi.hProcess);
- retval = _dbus_get_autolaunch_shm (address, &shm_name);
+
+ _dbus_verbose ("Wait until dbus-daemon is ready for connections (event handle %p)\n", ready_event_handle);
+
+ events[0] = ready_event_handle;
+ events[1] = pi.hProcess;
+ status = WaitForMultipleObjects (2, events, FALSE, 30000);
+
+ switch (status)
+ {
+ case WAIT_OBJECT_0:
+ /* ready event signalled, everything is okay */
+ retval = TRUE;
+ break;
+
+ case WAIT_OBJECT_0 + 1:
+ /* dbus-daemon process has exited */
+ dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED, "dbus-daemon exited before signalling ready");
+ goto out;
+
+ case WAIT_FAILED:
+ _dbus_win_set_error_from_last_error (error, "Unable to wait for server readiness (handle %p)", ready_event_handle);
+ goto out;
+
+ case WAIT_TIMEOUT:
+ /* GetLastError() is not set */
+ dbus_set_error (error, DBUS_ERROR_TIMEOUT, "Timed out waiting for server readiness or exit (handle %p)", ready_event_handle);
+ goto out;
+
+ default:
+ /* GetLastError() is probably not set? */
+ dbus_set_error (error, DBUS_ERROR_FAILED, "Unknown result '%lu' while waiting for server readiness (handle %p)", status, ready_event_handle);
+ goto out;
+ }
+ _dbus_verbose ("Got signal that dbus-daemon with process id '%ld' is ready for connections\n", GetProcessId (pi.hProcess));
+
+ if (autolaunch_handle_location != NULL)
+ {
+ *autolaunch_handle_location = pi.hProcess;
+ _dbus_verbose ("Returning process handle of started server (handle=%p)\n", pi.hProcess);
+ }
+ else
+ {
+ CloseHandle (pi.hProcess);
+ }
+
+ /* do not wait for the appearance of shm, we can assume that it is present */
+ retval = _dbus_get_autolaunch_shm (address, &shm_name, FALSE);
if (retval == FALSE)
dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to get autolaunch address from launched dbus-daemon");
}
@@ -3448,10 +3558,12 @@ out:
_dbus_platform_rmutex_free (lock);
_dbus_string_free (&shm_name);
_dbus_string_free (&dbus_args);
+ if (ready_event_handle)
+ _dbus_win_event_free (ready_event_handle, NULL);
+ _DBUS_ASSERT_ERROR_XOR_BOOL (error, retval);
return retval;
- }
-
+}
/** Makes the file readable by every user in the system.
*
diff --git a/dbus/dbus-sysdeps-win.h b/dbus/dbus-sysdeps-win.h
index 284bc796..5027f180 100644
--- a/dbus/dbus-sysdeps-win.h
+++ b/dbus/dbus-sysdeps-win.h
@@ -117,6 +117,10 @@ dbus_bool_t _dbus_daemon_publish_session_bus_address (const char *address,
DBUS_PRIVATE_EXPORT
DBusRMutex *_dbus_win_rmutex_named_new (const char* name);
+DBUS_PRIVATE_EXPORT
+void _dbus_test_win_autolaunch_set_command_line_parameter (const char *path);
+DBUS_PRIVATE_EXPORT
+void _dbus_test_win_set_autolaunch_handle_location (HANDLE *location);
#endif
/** @} end of sysdeps-win.h */
diff --git a/test/data/valid-config-files/listen-autolaunch-win.conf.in b/test/data/valid-config-files/listen-autolaunch-win.conf.in
new file mode 100644
index 00000000..7557e526
--- /dev/null
+++ b/test/data/valid-config-files/listen-autolaunch-win.conf.in
@@ -0,0 +1,11 @@
+
+
+ session
+ @TEST_LISTEN@
+
+
+
+
+
+
diff --git a/test/name-test/CMakeLists.txt b/test/name-test/CMakeLists.txt
index 1b3c0e5c..098993ae 100644
--- a/test/name-test/CMakeLists.txt
+++ b/test/name-test/CMakeLists.txt
@@ -1,6 +1,10 @@
add_definitions(${DBUS_INTERNAL_CLIENT_DEFINITIONS})
-add_helper_executable(test-autolaunch test-autolaunch.c dbus-testutils)
+if(WIN32)
+ add_test_executable(test-autolaunch-win test-autolaunch-win.c ${DBUS_INTERNAL_LIBRARIES} dbus-testutils)
+else()
+ add_helper_executable(test-autolaunch test-autolaunch.c dbus-testutils)
+endif()
add_session_test_executable(test-ids test-ids.c ${DBUS_INTERNAL_LIBRARIES})
add_session_test_executable(test-pending-call-disconnected test-pending-call-disconnected.c ${DBUS_INTERNAL_LIBRARIES})
diff --git a/test/name-test/Makefile.am b/test/name-test/Makefile.am
index 81938778..527dbbff 100644
--- a/test/name-test/Makefile.am
+++ b/test/name-test/Makefile.am
@@ -72,7 +72,7 @@ if DBUS_ENABLE_EMBEDDED_TESTS
## we use noinst_PROGRAMS not check_PROGRAMS for TESTS so that we
## build even when not doing "make check"
-noinst_PROGRAMS=test-pending-call-dispatch test-pending-call-timeout test-pending-call-disconnected test-threads-init test-ids test-shutdown test-privserver-client test-autolaunch
+noinst_PROGRAMS=test-pending-call-dispatch test-pending-call-timeout test-pending-call-disconnected test-threads-init test-ids test-shutdown test-privserver-client
test_pending_call_dispatch_LDADD = \
$(CODE_COVERAGE_LIBS) \
@@ -103,9 +103,21 @@ test_privserver_client_LDADD = \
$(CODE_COVERAGE_LIBS) \
../libdbus-testutils.la \
$(NULL)
+
+if DBUS_WIN
+noinst_PROGRAMS += test-autolaunch-win
+test_autolaunch_win_SOURCES = test-autolaunch-win.c
+test_autolaunch_win_LDADD = \
+ $(CODE_COVERAGE_LIBS) \
+ ../libdbus-testutils.la \
+ $(NULL)
+TESTS += test-autolaunch-win
+else
+noinst_PROGRAMS += test-autolaunch
+test_autolaunch_SOURCES = test-autolaunch.c
test_autolaunch_LDADD = \
$(CODE_COVERAGE_LIBS) \
../libdbus-testutils.la \
$(NULL)
-
+endif
endif
diff --git a/test/name-test/test-autolaunch-win.c b/test/name-test/test-autolaunch-win.c
new file mode 100644
index 00000000..8a434e2c
--- /dev/null
+++ b/test/name-test/test-autolaunch-win.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright © 2018-2022 Ralf Habacker
+ * SPDX-License-Identifier: MIT
+ */
+
+/**
+ * This test checks whether a client can connect to a dbus daemon configured
+ * for a default, user-defined and installation path related autostart and
+ * whether it can connect to a server having a different autolaunch
+ * configuration.
+ */
+
+#include "config.h"
+
+#include "dbus/dbus-file.h"
+#include "dbus/dbus-internals.h"
+#include "dbus/dbus-sysdeps.h"
+#include "dbus/dbus-test-tap.h"
+#include "dbus/dbus-test.h"
+#include "dbus/dbus.h"
+#include "test/test-utils.h"
+
+#include
+#include
+#include
+#ifdef HAVE_UNISTD_H
+#include
+#endif
+
+/* dbus_bus_get does not work yet */
+static dbus_bool_t use_bus_get = FALSE;
+
+static int add_wait_time = 0;
+
+#define oom() _dbus_test_fatal ("Out of memory")
+
+/**
+ * helper function
+ */
+#define _dbus_error_set_from_message_with_location(a, b) __dbus_error_set_from_message_with_location (__FILE__, __LINE__, __FUNCTION__, a, b)
+
+static void
+__dbus_error_set_from_message_with_location (const char *file, int line, const char *function, DBusError *error, DBusMessage *message)
+{
+ char *str = NULL;
+ dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &str,
+ DBUS_TYPE_INVALID);
+ dbus_set_error (error, dbus_message_get_error_name (message), "[%s(%d):%s] %s", file, line, function, str ? str : "");
+}
+
+static dbus_bool_t
+call_method (DBusConnection *conn,
+ DBusError *error,
+ int timeout,
+ const char *interface,
+ const char *method_str)
+{
+ DBusMessage *method;
+ DBusMessage *reply;
+ dbus_bool_t result = TRUE;
+
+ dbus_error_init (error);
+
+ method = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ interface,
+ method_str);
+
+ reply = dbus_connection_send_with_reply_and_block (conn, method, timeout, error);
+ dbus_message_unref (method);
+ if (reply == NULL)
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED, "Got no reply");
+ result = FALSE;
+ goto out;
+ }
+
+ if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ _dbus_error_set_from_message_with_location (error, reply);
+ result = FALSE;
+ goto out;
+ }
+ result = TRUE;
+
+out:
+ _DBUS_ASSERT_ERROR_XOR_BOOL (error, result);
+ dbus_message_unref (reply);
+ return result;
+}
+
+static dbus_bool_t
+_server_check_connection (DBusConnection *conn,
+ DBusError *error)
+{
+ if (use_bus_get)
+ return call_method (conn, error, -1, DBUS_INTERFACE_PEER, "GetMachineId");
+ else
+ return call_method (conn, error, -1, DBUS_INTERFACE_DBUS, "Hello");
+}
+
+static HANDLE autolaunch_handle = NULL;
+
+static dbus_bool_t
+_server_shutdown (DBusConnection *conn,
+ const char *scope,
+ int timeout,
+ DBusError *error)
+{
+ _dbus_assert (autolaunch_handle != NULL);
+
+ _dbus_test_diag ("Shutting down dbus-daemon (handle=%p)", autolaunch_handle);
+ if (!TerminateProcess (autolaunch_handle, 1))
+ _dbus_test_fatal ("Unable to terminate dbus-daemon (handle=%p) : %s",
+ /* this string is leaked, but we're crashing anyway */
+ autolaunch_handle, _dbus_win_error_string (GetLastError ()));
+
+ _dbus_test_diag ("Return value from closing autolaunch_handle is %d", CloseHandle (autolaunch_handle));
+ autolaunch_handle = NULL;
+ _dbus_test_win_set_autolaunch_handle_location (NULL);
+ return TRUE;
+}
+
+typedef enum
+{
+ RUN_TEST_DEFAULT = 0,
+ RUN_TEST_EXPECT_CONNECTION_TO_FAIL = (1 << 0),
+} RunTestFlags;
+
+static dbus_bool_t
+check_results (DBusConnection *conn,
+ DBusString *server_address,
+ DBusString *address,
+ const char *scope,
+ RunTestFlags flags,
+ DBusError *error)
+{
+ if (add_wait_time)
+ _dbus_sleep_milliseconds (add_wait_time);
+
+ if (dbus_error_is_set (error))
+ _dbus_test_diag ("Error is set: %s %s", error->name, error->message);
+
+ if (conn == NULL)
+ {
+ if (!dbus_error_is_set (error))
+ _dbus_test_fatal ("Failed to autolaunch session bus and no error was set");
+
+ if (flags & RUN_TEST_EXPECT_CONNECTION_TO_FAIL)
+ return TRUE;
+
+ _dbus_test_diag ("autolaunch unexpectedly failed: %s: %s", error->name, error->message);
+ return FALSE;
+ }
+ else
+ {
+ if (dbus_error_is_set (error))
+ _dbus_test_fatal ("Successfully autolaunched session bus but error was set: %s: %s", error->name, error->message);
+
+ if (flags & RUN_TEST_EXPECT_CONNECTION_TO_FAIL)
+ {
+ _dbus_test_diag ("autolaunch unexpectedly succeeded");
+ return FALSE;
+ }
+ _dbus_test_diag ("Client connection succeeded - uses '%s'", _dbus_string_get_const_data (address));
+ }
+
+ if (add_wait_time)
+ _dbus_sleep_milliseconds (add_wait_time);
+
+ _dbus_test_diag ("Server returned bus address '%s'", _dbus_string_get_const_data (server_address));
+ if (!_server_check_connection (conn, error))
+ {
+ _dbus_test_diag ("Could not execute server function");
+ return FALSE;
+ }
+ else
+ _dbus_test_diag ("Calling server function succeeded");
+
+ return TRUE;
+}
+
+static dbus_bool_t
+run_test (const char *server_scope, const char *scope, const char *test_data_dir, RunTestFlags flags)
+{
+ DBusConnection *conn = NULL;
+ DBusError error;
+ DBusString server_address = _DBUS_STRING_INIT_INVALID;
+ DBusString address = _DBUS_STRING_INIT_INVALID;
+ DBusString session_parameter = _DBUS_STRING_INIT_INVALID;
+ dbus_bool_t result = FALSE;
+ TestMainContext *ctx;
+ _dbus_assert (test_data_dir);
+
+ ctx = test_main_context_get ();
+
+ dbus_error_init (&error);
+
+ if (!_dbus_string_init (&server_address))
+ oom ();
+
+ if (!_dbus_string_init (&address))
+ oom ();
+
+ _dbus_test_diag ("run test");
+
+ if (*server_scope != '\0')
+ {
+ if (!_dbus_string_append_printf (&server_address, "autolaunch:scope=%s", server_scope))
+ oom ();
+ }
+ else if (!_dbus_string_append_printf (&server_address, "autolaunch:"))
+ {
+ oom ();
+ }
+
+ if (*scope != '\0')
+ {
+ if (!_dbus_string_append_printf (&address, "autolaunch:scope=%s", scope))
+ oom ();
+ }
+ else if (!_dbus_string_append_printf (&address, "autolaunch:"))
+ {
+ oom ();
+ }
+
+ if (!_dbus_string_init (&session_parameter))
+ oom ();
+
+ /* We haven't implemented any form of escaping quotes,
+ * but Windows doesn't allow filenames to contain quotes
+ * so it shouldn't matter. */
+ _dbus_test_check (strchr (test_data_dir, '"') == NULL);
+
+ _dbus_test_check (strchr (_dbus_string_get_const_data (&server_address), '"') == NULL);
+
+ if (!_dbus_string_append_printf (&session_parameter, "\"--config-file=%s/%s\" \"--address=%s\"", test_data_dir, "valid-config-files/listen-autolaunch-win.conf", _dbus_string_get_const_data (&server_address)))
+ {
+ oom ();
+ }
+
+ _dbus_test_win_autolaunch_set_command_line_parameter (_dbus_string_get_const_data (&session_parameter));
+
+ _dbus_test_diag ("Autolaunch handle initially %p", autolaunch_handle);
+ _dbus_test_win_set_autolaunch_handle_location (&autolaunch_handle);
+
+ if (use_bus_get)
+ {
+ dbus_setenv ("DBUS_SESSION_BUS_ADDRESS", _dbus_string_get_const_data (&address));
+ _dbus_test_diag ("got env %s", getenv ("DBUS_SESSION_BUS_ADDRESS"));
+ conn = dbus_bus_get_private (DBUS_BUS_SESSION, &error);
+ dbus_connection_set_exit_on_disconnect (conn, FALSE);
+ }
+ else
+ {
+ conn = dbus_connection_open_private (_dbus_string_get_const_data (&address), &error);
+ }
+
+ _dbus_test_diag ("After attempting to connect: autolaunch handle is %p", autolaunch_handle);
+ if (conn)
+ test_connection_setup (ctx, conn);
+
+ result = check_results (conn, &server_address, &address, scope, flags, &error);
+
+ if (conn)
+ {
+ _dbus_test_diag("Shutdown connection '%p'", conn);
+ test_connection_shutdown (ctx, conn);
+ dbus_connection_close (conn);
+ dbus_connection_unref (conn);
+ }
+
+ _server_shutdown (conn, scope, -1, &error);
+ _dbus_test_diag ("server has been shut down");
+
+ _dbus_string_free (&address);
+ _dbus_string_free (&server_address);
+ _dbus_string_free (&session_parameter);
+
+ test_main_context_unref (ctx);
+
+ return result;
+}
+
+static dbus_bool_t
+run_test_okay (const char *scope, const char *test_data_dir)
+{
+ return run_test (scope, scope, test_data_dir, RUN_TEST_DEFAULT);
+}
+
+static dbus_bool_t
+_dbus_autolaunch_default_test (const char *test_data_dir)
+{
+ return run_test_okay ("", test_data_dir);
+}
+
+static dbus_bool_t
+_dbus_autolaunch_custom_scope_test (const char *test_data_dir)
+{
+ return run_test_okay ("123", test_data_dir);
+}
+
+static dbus_bool_t
+_dbus_autolaunch_install_path_scope_test (const char *test_data_dir)
+{
+ return run_test_okay ("*install-path", test_data_dir);
+}
+
+static dbus_bool_t
+_dbus_autolaunch_user_scope_test (const char *test_data_dir)
+{
+ return run_test_okay ("*user", test_data_dir);
+}
+
+static dbus_bool_t
+_dbus_autolaunch_loop_test (const char *test_data_dir, dbus_bool_t same_scope)
+{
+ int i;
+ int max = 10;
+
+ for (i = 0; i < max; i++)
+ {
+ char s[2] = { i+'A', 0 };
+ if (!run_test_okay (same_scope ? "A" : s, test_data_dir))
+ _dbus_test_not_ok ("%d", max);
+ else
+ _dbus_test_ok ("%d", max);
+ if (add_wait_time)
+ _dbus_sleep_milliseconds (add_wait_time);
+ }
+ return TRUE;
+}
+
+static dbus_bool_t
+_dbus_autolaunch_same_scope_loop_test (const char *test_data_dir)
+{
+ return _dbus_autolaunch_loop_test (test_data_dir, TRUE);
+}
+
+static dbus_bool_t
+_dbus_autolaunch_different_scope_loop_test (const char *test_data_dir)
+{
+ return _dbus_autolaunch_loop_test (test_data_dir, FALSE);
+}
+
+static DBusTestCase tests[] = {
+ { "default", _dbus_autolaunch_default_test },
+ { "custom", _dbus_autolaunch_custom_scope_test },
+ { "install-path", _dbus_autolaunch_install_path_scope_test },
+ { "user", _dbus_autolaunch_user_scope_test },
+ { "loop", _dbus_autolaunch_same_scope_loop_test },
+ { "different-scope-loop", _dbus_autolaunch_different_scope_loop_test },
+};
+
+int
+main (int argc,
+ char **argv)
+{
+ return _dbus_test_main (argc, argv, _DBUS_N_ELEMENTS (tests), tests,
+ DBUS_TEST_FLAGS_CHECK_MEMORY_LEAKS,
+ NULL, NULL);
+}