]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
Add a test application for autostart on Windows implementation
authorRalf Habacker <ralf.habacker@freenet.de>
Wed, 17 Nov 2021 09:51:39 +0000 (10:51 +0100)
committerRalf Habacker <ralf.habacker@freenet.de>
Mon, 27 Jun 2022 13:34:23 +0000 (15:34 +0200)
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>
test/data/valid-config-files/listen-autolaunch-win.conf.in [new file with mode: 0644]
test/name-test/CMakeLists.txt
test/name-test/Makefile.am
test/name-test/test-autolaunch-win.c [new file with mode: 0644]

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 (file)
index 0000000..7557e52
--- /dev/null
@@ -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>
index 1b3c0e5c72a4f095b8cbdc84ce0b7538d88660a9..098993aeea4572c273cfa9221d2d39155349710e 100644 (file)
@@ -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})
index 8193877859c16ff1651778229ed827c1a487df5c..527dbbff89d498f77e2d2a47a26ae3d2ac31ccb4 100644 (file)
@@ -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 (file)
index 0000000..8a434e2
--- /dev/null
@@ -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);
+}