diff options
author | Ralf Habacker <ralf.habacker@freenet.de> | 2021-11-17 10:51:39 +0100 |
---|---|---|
committer | Ralf Habacker <ralf.habacker@freenet.de> | 2022-06-27 15:34:23 +0200 |
commit | b1dd6fa7a62e42d9f38d73d28a3bf1c1618e8b32 (patch) | |
tree | 7e569a2cfd8e618b7e11bcfa5d7ef85448fbeb65 | |
parent | 556eb2ea1ac2c24022313cf2b70bda2f242ba4a1 (diff) | |
download | dbus-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.in | 11 | ||||
-rw-r--r-- | test/name-test/CMakeLists.txt | 6 | ||||
-rw-r--r-- | test/name-test/Makefile.am | 16 | ||||
-rw-r--r-- | test/name-test/test-autolaunch-win.c | 363 |
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); +} |