[glib: 6/7] tests: Add tests for GDebugController




commit b7d3e3f16edb2e6dc5a8ecbac837a258928987ea
Author: Philip Withnall <pwithnall endlessos org>
Date:   Thu Feb 10 19:24:42 2022 +0000

    tests: Add tests for GDebugController
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>
    
    Fixes: #1190

 gio/tests/debugcontroller.c | 396 ++++++++++++++++++++++++++++++++++++++++++++
 gio/tests/meson.build       |   1 +
 2 files changed, 397 insertions(+)
---
diff --git a/gio/tests/debugcontroller.c b/gio/tests/debugcontroller.c
new file mode 100644
index 000000000..c20acd659
--- /dev/null
+++ b/gio/tests/debugcontroller.c
@@ -0,0 +1,396 @@
+/* GLib testing framework examples and tests
+ *
+ * Copyright © 2022 Endless OS Foundation, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ * Author: Philip Withnall <pwithnall endlessos org>
+ */
+
+#include <gio/gio.h>
+#include <locale.h>
+
+
+static void
+test_dbus_basic (void)
+{
+  GTestDBus *bus;
+  GDBusConnection *connection = NULL, *connection2 = NULL;
+  GDebugControllerDBus *controller = NULL;
+  gboolean old_value;
+  gboolean debug_enabled;
+  GError *local_error = NULL;
+
+  g_test_summary ("Smoketest for construction and setting of a #GDebugControllerDBus.");
+
+  /* Set up a test session bus and connection. */
+  bus = g_test_dbus_new (G_TEST_DBUS_NONE);
+  g_test_dbus_up (bus);
+
+  connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &local_error);
+  g_assert_no_error (local_error);
+
+  /* Create a controller for this process. */
+  controller = g_debug_controller_dbus_new (connection, NULL, &local_error);
+  g_assert_no_error (local_error);
+  g_assert_nonnull (controller);
+  g_assert_true (G_IS_DEBUG_CONTROLLER_DBUS (controller));
+
+  /* Try enabling and disabling debug output from within the process. */
+  old_value = g_debug_controller_get_debug_enabled (G_DEBUG_CONTROLLER (controller));
+
+  g_debug_controller_set_debug_enabled (G_DEBUG_CONTROLLER (controller), TRUE);
+  g_assert_true (g_debug_controller_get_debug_enabled (G_DEBUG_CONTROLLER (controller)));
+
+  g_debug_controller_set_debug_enabled (G_DEBUG_CONTROLLER (controller), FALSE);
+  g_assert_false (g_debug_controller_get_debug_enabled (G_DEBUG_CONTROLLER (controller)));
+
+  /* Reset the debug state and check using g_object_get(), to exercise that. */
+  g_debug_controller_set_debug_enabled (G_DEBUG_CONTROLLER (controller), old_value);
+
+  g_object_get (G_OBJECT (controller),
+                "debug-enabled", &debug_enabled,
+                "connection", &connection2,
+                NULL);
+  g_assert_true (debug_enabled == old_value);
+  g_assert_true (connection2 == connection);
+  g_clear_object (&connection2);
+
+  g_debug_controller_dbus_stop (controller);
+  while (g_main_context_iteration (NULL, FALSE));
+  g_assert_finalize_object (controller);
+  g_clear_object (&connection);
+
+  g_test_dbus_down (bus);
+  g_clear_object (&bus);
+}
+
+static void
+test_dbus_duplicate (void)
+{
+  GTestDBus *bus;
+  GDBusConnection *connection = NULL;
+  GDebugControllerDBus *controller1 = NULL, *controller2 = NULL;
+  GError *local_error = NULL;
+
+  g_test_summary ("Test that creating a second #GDebugControllerDBus on the same D-Bus connection fails.");
+
+  /* Set up a test session bus and connection. */
+  bus = g_test_dbus_new (G_TEST_DBUS_NONE);
+  g_test_dbus_up (bus);
+
+  connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &local_error);
+  g_assert_no_error (local_error);
+
+  /* Create a controller for this process. */
+  controller1 = g_debug_controller_dbus_new (connection, NULL, &local_error);
+  g_assert_no_error (local_error);
+  g_assert_nonnull (controller1);
+
+  /* And try creating a second one. */
+  controller2 = g_debug_controller_dbus_new (connection, NULL, &local_error);
+  g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS);
+  g_assert_null (controller2);
+  g_clear_error (&local_error);
+
+  g_debug_controller_dbus_stop (controller1);
+  while (g_main_context_iteration (NULL, FALSE));
+  g_assert_finalize_object (controller1);
+  g_clear_object (&connection);
+
+  g_test_dbus_down (bus);
+  g_clear_object (&bus);
+}
+
+static void
+async_result_cb (GObject      *source_object,
+                 GAsyncResult *result,
+                 gpointer      user_data)
+{
+  GAsyncResult **result_out = user_data;
+
+  g_assert_null (*result_out);
+  *result_out = g_object_ref (result);
+
+  g_main_context_wakeup (g_main_context_get_thread_default ());
+}
+
+static gboolean
+authorize_false_cb (GDebugControllerDBus  *debug_controller,
+                    GDBusMethodInvocation *invocation,
+                    gpointer               user_data)
+{
+  return FALSE;
+}
+
+static gboolean
+authorize_true_cb (GDebugControllerDBus  *debug_controller,
+                   GDBusMethodInvocation *invocation,
+                   gpointer               user_data)
+{
+  return TRUE;
+}
+
+static void
+notify_debug_enabled_cb (GObject    *object,
+                         GParamSpec *pspec,
+                         gpointer    user_data)
+{
+  guint *notify_count_out = user_data;
+
+  *notify_count_out = *notify_count_out + 1;
+}
+
+static void
+properties_changed_cb (GDBusConnection *connection,
+                       const gchar     *sender_name,
+                       const gchar     *object_path,
+                       const gchar     *interface_name,
+                       const gchar     *signal_name,
+                       GVariant        *parameters,
+                       gpointer         user_data)
+{
+  guint *properties_changed_count_out = user_data;
+
+  *properties_changed_count_out = *properties_changed_count_out + 1;
+  g_main_context_wakeup (g_main_context_get_thread_default ());
+}
+
+static void
+test_dbus_properties (void)
+{
+  GTestDBus *bus;
+  GDBusConnection *controller_connection = NULL;
+  GDBusConnection *remote_connection = NULL;
+  GDebugControllerDBus *controller = NULL;
+  gboolean old_value;
+  GAsyncResult *result = NULL;
+  GVariant *reply = NULL;
+  GVariant *debug_enabled_variant = NULL;
+  gboolean debug_enabled;
+  GError *local_error = NULL;
+  gulong handler_id;
+  gulong notify_id;
+  guint notify_count = 0;
+  guint properties_changed_id;
+  guint properties_changed_count = 0;
+
+  g_test_summary ("Test getting and setting properties on a #GDebugControllerDBus.");
+
+  /* Set up a test session bus and connection. Set up a separate second
+   * connection to simulate a remote peer. */
+  bus = g_test_dbus_new (G_TEST_DBUS_NONE);
+  g_test_dbus_up (bus);
+
+  controller_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &local_error);
+  g_assert_no_error (local_error);
+
+  remote_connection = g_dbus_connection_new_for_address_sync (g_test_dbus_get_bus_address (bus),
+                                                              G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+                                                              G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
+                                                              NULL,
+                                                              NULL,
+                                                              &local_error);
+  g_assert_no_error (local_error);
+
+  /* Create a controller for this process. */
+  controller = g_debug_controller_dbus_new (controller_connection, NULL, &local_error);
+  g_assert_no_error (local_error);
+  g_assert_nonnull (controller);
+  g_assert_true (G_IS_DEBUG_CONTROLLER_DBUS (controller));
+
+  old_value = g_debug_controller_get_debug_enabled (G_DEBUG_CONTROLLER (controller));
+  notify_id = g_signal_connect (controller, "notify::debug-enabled", G_CALLBACK (notify_debug_enabled_cb), 
&notify_count);
+
+  properties_changed_id = g_dbus_connection_signal_subscribe (remote_connection,
+                                                              g_dbus_connection_get_unique_name 
(controller_connection),
+                                                              "org.freedesktop.DBus.Properties",
+                                                              "PropertiesChanged",
+                                                              "/org/gtk/Debugging",
+                                                              NULL,
+                                                              G_DBUS_SIGNAL_FLAGS_NONE,
+                                                              properties_changed_cb,
+                                                              &properties_changed_count,
+                                                              NULL);
+
+  /* Get the debug status remotely. */
+  g_dbus_connection_call (remote_connection,
+                          g_dbus_connection_get_unique_name (controller_connection),
+                          "/org/gtk/Debugging",
+                          "org.freedesktop.DBus.Properties",
+                          "Get",
+                          g_variant_new ("(ss)", "org.gtk.Debugging", "DebugEnabled"),
+                          G_VARIANT_TYPE ("(v)"),
+                          G_DBUS_CALL_FLAGS_NONE,
+                          -1,
+                          NULL,
+                          async_result_cb,
+                          &result);
+  g_assert_no_error (local_error);
+
+  while (result == NULL)
+    g_main_context_iteration (NULL, TRUE);
+
+  reply = g_dbus_connection_call_finish (remote_connection, result, &local_error);
+  g_assert_no_error (local_error);
+  g_clear_object (&result);
+
+  g_variant_get (reply, "(v)", &debug_enabled_variant);
+  debug_enabled = g_variant_get_boolean (debug_enabled_variant);
+  g_assert_true (debug_enabled == old_value);
+  g_assert_cmpuint (notify_count, ==, 0);
+  g_assert_cmpuint (properties_changed_count, ==, 0);
+
+  g_clear_pointer (&debug_enabled_variant, g_variant_unref);
+  g_clear_pointer (&reply, g_variant_unref);
+
+  /* Set the debug status remotely. The first attempt should fail due to no
+   * authorisation handler being connected. The second should fail due to the
+   * now-connected handler returning %FALSE. The third attempt should
+   * succeed. */
+  g_dbus_connection_call (remote_connection,
+                          g_dbus_connection_get_unique_name (controller_connection),
+                          "/org/gtk/Debugging",
+                          "org.gtk.Debugging",
+                          "SetDebugEnabled",
+                          g_variant_new ("(b)", !old_value),
+                          NULL,
+                          G_DBUS_CALL_FLAGS_NONE,
+                          -1,
+                          NULL,
+                          async_result_cb,
+                          &result);
+
+  while (result == NULL)
+    g_main_context_iteration (NULL, TRUE);
+
+  reply = g_dbus_connection_call_finish (remote_connection, result, &local_error);
+  g_assert_error (local_error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED);
+  g_clear_object (&result);
+  g_clear_error (&local_error);
+
+  g_assert_true (g_debug_controller_get_debug_enabled (G_DEBUG_CONTROLLER (controller)) == old_value);
+  g_assert_cmpuint (notify_count, ==, 0);
+  g_assert_cmpuint (properties_changed_count, ==, 0);
+
+  g_clear_pointer (&debug_enabled_variant, g_variant_unref);
+  g_clear_pointer (&reply, g_variant_unref);
+
+  /* Attach an authorisation handler and try again. */
+  handler_id = g_signal_connect (controller, "authorize", G_CALLBACK (authorize_false_cb), NULL);
+
+  g_dbus_connection_call (remote_connection,
+                          g_dbus_connection_get_unique_name (controller_connection),
+                          "/org/gtk/Debugging",
+                          "org.gtk.Debugging",
+                          "SetDebugEnabled",
+                          g_variant_new ("(b)", !old_value),
+                          NULL,
+                          G_DBUS_CALL_FLAGS_NONE,
+                          -1,
+                          NULL,
+                          async_result_cb,
+                          &result);
+
+  while (result == NULL)
+    g_main_context_iteration (NULL, TRUE);
+
+  reply = g_dbus_connection_call_finish (remote_connection, result, &local_error);
+  g_assert_error (local_error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED);
+  g_clear_object (&result);
+  g_clear_error (&local_error);
+
+  g_assert_true (g_debug_controller_get_debug_enabled (G_DEBUG_CONTROLLER (controller)) == old_value);
+  g_assert_cmpuint (notify_count, ==, 0);
+  g_assert_cmpuint (properties_changed_count, ==, 0);
+
+  g_clear_pointer (&debug_enabled_variant, g_variant_unref);
+  g_clear_pointer (&reply, g_variant_unref);
+
+  g_signal_handler_disconnect (controller, handler_id);
+  handler_id = 0;
+
+  /* Attach another signal handler which will grant access, and try again. */
+  handler_id = g_signal_connect (controller, "authorize", G_CALLBACK (authorize_true_cb), NULL);
+
+  g_dbus_connection_call (remote_connection,
+                          g_dbus_connection_get_unique_name (controller_connection),
+                          "/org/gtk/Debugging",
+                          "org.gtk.Debugging",
+                          "SetDebugEnabled",
+                          g_variant_new ("(b)", !old_value),
+                          NULL,
+                          G_DBUS_CALL_FLAGS_NONE,
+                          -1,
+                          NULL,
+                          async_result_cb,
+                          &result);
+
+  while (result == NULL)
+    g_main_context_iteration (NULL, TRUE);
+
+  reply = g_dbus_connection_call_finish (remote_connection, result, &local_error);
+  g_assert_no_error (local_error);
+  g_clear_object (&result);
+
+  g_assert_true (g_debug_controller_get_debug_enabled (G_DEBUG_CONTROLLER (controller)) == !old_value);
+  g_assert_cmpuint (notify_count, ==, 1);
+  g_assert_cmpuint (properties_changed_count, ==, 1);
+
+  g_clear_pointer (&debug_enabled_variant, g_variant_unref);
+  g_clear_pointer (&reply, g_variant_unref);
+
+  g_signal_handler_disconnect (controller, handler_id);
+  handler_id = 0;
+
+  /* Set the debug status locally. */
+  g_debug_controller_set_debug_enabled (G_DEBUG_CONTROLLER (controller), old_value);
+  g_assert_true (g_debug_controller_get_debug_enabled (G_DEBUG_CONTROLLER (controller)) == old_value);
+  g_assert_cmpuint (notify_count, ==, 2);
+
+  while (properties_changed_count != 2)
+    g_main_context_iteration (NULL, TRUE);
+
+  g_assert_cmpuint (properties_changed_count, ==, 2);
+
+  g_signal_handler_disconnect (controller, notify_id);
+  notify_id = 0;
+
+  g_dbus_connection_signal_unsubscribe (remote_connection, properties_changed_id);
+  properties_changed_id = 0;
+
+  g_debug_controller_dbus_stop (controller);
+  while (g_main_context_iteration (NULL, FALSE));
+  g_assert_finalize_object (controller);
+  g_clear_object (&controller_connection);
+  g_clear_object (&remote_connection);
+
+  g_test_dbus_down (bus);
+  g_clear_object (&bus);
+}
+
+int
+main (int   argc,
+      char *argv[])
+{
+  setlocale (LC_ALL, "");
+  g_test_init (&argc, &argv, NULL);
+
+  g_test_add_func ("/debug-controller/dbus/basic", test_dbus_basic);
+  g_test_add_func ("/debug-controller/dbus/duplicate", test_dbus_duplicate);
+  g_test_add_func ("/debug-controller/dbus/properties", test_dbus_properties);
+
+  return g_test_run ();
+}
diff --git a/gio/tests/meson.build b/gio/tests/meson.build
index 017749c1c..43bc9d76f 100644
--- a/gio/tests/meson.build
+++ b/gio/tests/meson.build
@@ -57,6 +57,7 @@ gio_tests = {
   },
   'data-input-stream' : {},
   'data-output-stream' : {},
+  'debugcontroller' : {},
   'defaultvalue' : {'extra_sources' : [giotypefuncs_inc]},
   'fileattributematcher' : {},
   'filter-streams' : {},


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]