summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalf Habacker <ralf.habacker@freenet.de>2021-11-17 10:51:39 +0100
committerRalf Habacker <ralf.habacker@freenet.de>2022-06-27 15:34:23 +0200
commitb1dd6fa7a62e42d9f38d73d28a3bf1c1618e8b32 (patch)
tree7e569a2cfd8e618b7e11bcfa5d7ef85448fbeb65
parent556eb2ea1ac2c24022313cf2b70bda2f242ba4a1 (diff)
downloaddbus-b1dd6fa7a62e42d9f38d73d28a3bf1c1618e8b32.tar.gz
Add a test application for autostart on Windows implementation
The test application performs several individual tests to detect possible problems with the autostart support under Windows. Connections are tested with the standard scope, a 'custom' scope, the 'install path' scope and the 'user' scope. Signed-off-by: Ralf Habacker <ralf.habacker@freenet.de>
-rw-r--r--test/data/valid-config-files/listen-autolaunch-win.conf.in11
-rw-r--r--test/name-test/CMakeLists.txt6
-rw-r--r--test/name-test/Makefile.am16
-rw-r--r--test/name-test/test-autolaunch-win.c363
4 files changed, 393 insertions, 3 deletions
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 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <type>session</type>
+ <listen>@TEST_LISTEN@</listen>
+ <policy context="default">
+ <allow send_destination="*" eavesdrop="true"/>
+ <allow eavesdrop="true"/>
+ <allow own="*"/>
+ </policy>
+</busconfig>
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 <ralf.habacker@freenet.de>
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#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);
+}