[dconf/wip/reorg: 487/498] Add test for dbus backends



commit e60fa3a5ddcde7cb1dcf12f56368c8c88c333304
Author: Ryan Lortie <desrt desrt ca>
Date:   Thu Jul 5 23:51:42 2012 -0400

    Add test for dbus backends
    
    Currently we test the gdbus-thread and gdbus-filter backends.
    
    It should be possible to use the same code (with minor changes) once the
    dbus-1 backend is ported to the new world order.

 tests/.gitignore  |    2 +
 tests/Makefile.am |   14 ++
 tests/dbus.c      |  392 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 408 insertions(+), 0 deletions(-)
---
diff --git a/tests/.gitignore b/tests/.gitignore
index 5dac741..2ad0a97 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,4 +1,6 @@
 dbus1
+gdbus-filter
+gdbus-thread
 gsettings
 gvdb
 paths
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f166ef5..960d72c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -17,3 +17,17 @@ gvdb_LDADD = $(glib_LIBS)
 gvdb_SOURCES = \
 	../gvdb/gvdb-reader.c		\
 	gvdb.c
+
+TEST_PROGS += gdbus-thread
+gdbus_thread_CFLAGS = $(AM_CFLAGS) -DDBUS_BACKEND=\"/gdbus/thread\"
+gdbus_thread_LDADD = $(gio_LIBS)
+gdbus_thread_SOURCES = \
+	../gdbus/dconf-gdbus-thread.c	\
+	dbus.c
+
+TEST_PROGS += gdbus-filter
+gdbus_filter_CFLAGS = $(AM_CFLAGS) -DDBUS_BACKEND=\"/gdbus/filter\"
+gdbus_filter_LDADD = $(gio_LIBS)
+gdbus_filter_SOURCES = \
+	../gdbus/dconf-gdbus-filter.c	\
+	dbus.c
diff --git a/tests/dbus.c b/tests/dbus.c
new file mode 100644
index 0000000..e227266
--- /dev/null
+++ b/tests/dbus.c
@@ -0,0 +1,392 @@
+#include <string.h>
+#include <glib.h>
+#include <stdlib.h>
+
+/* Test the DBus communicaton code.
+ */
+
+#include "dconf-engine.h"
+
+static gboolean okay_in_main;
+static GThread *main_thread;
+static GThread *dbus_thread;
+static GQueue   async_call_success_queue;
+static GQueue   async_call_error_queue;
+static GMutex   async_call_queue_lock;
+static GCond    async_call_queue_cond;
+static gboolean signal_was_received;
+
+void
+dconf_engine_call_handle_reply (DConfEngineCallHandle *handle,
+                                GVariant              *parameters,
+                                const GError          *error)
+{
+  DConfEngineCallHandle *expected_handle;
+
+  /* Ensure that messages are never delivered in the main thread except
+   * by way of a mainloop (ie: not during sync calls).
+   *
+   * It's okay if they are delivered in another thread at the same time
+   * as a sync call is happening in the main thread, though...
+   */
+  g_assert (g_thread_self () != main_thread || okay_in_main);
+
+  /* Make sure that we only ever receive D-Bus calls from a single
+   * thread.
+   */
+  if (!dbus_thread)
+    dbus_thread = g_thread_self ();
+  g_assert (g_thread_self () == dbus_thread);
+
+  /* This is the passing case. */
+  if (parameters != NULL)
+    {
+      g_mutex_lock (&async_call_queue_lock);
+      g_assert (g_queue_is_empty (&async_call_error_queue));
+      expected_handle = g_queue_pop_head (&async_call_success_queue);
+      g_mutex_unlock (&async_call_queue_lock);
+
+      g_assert (parameters != NULL);
+      g_assert (error == NULL);
+      g_assert (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(s)")));
+
+      g_assert (expected_handle == handle);
+      g_free (handle);
+
+      g_mutex_lock (&async_call_queue_lock);
+      if (g_queue_is_empty (&async_call_success_queue))
+        g_cond_broadcast (&async_call_queue_cond);
+      g_mutex_unlock (&async_call_queue_lock);
+    }
+  else
+    {
+      g_mutex_lock (&async_call_queue_lock);
+      g_assert (g_queue_is_empty (&async_call_success_queue));
+      expected_handle = g_queue_pop_head (&async_call_error_queue);
+      g_mutex_unlock (&async_call_queue_lock);
+
+      g_assert (parameters == NULL);
+      g_assert (error != NULL);
+
+      g_assert (expected_handle == handle);
+      g_free (handle);
+
+      g_mutex_lock (&async_call_queue_lock);
+      if (g_queue_is_empty (&async_call_error_queue))
+        g_cond_broadcast (&async_call_queue_cond);
+      g_mutex_unlock (&async_call_queue_lock);
+    }
+}
+
+void
+dconf_engine_handle_dbus_signal (GBusType     bus_type,
+                                 const gchar *bus_name,
+                                 const gchar *object_path,
+                                 const gchar *signal_name,
+                                 GVariant    *parameters)
+{
+  g_assert (g_thread_self () != main_thread || okay_in_main);
+
+  if (!dbus_thread)
+    dbus_thread = g_thread_self ();
+  g_assert (g_thread_self () == dbus_thread);
+
+  if (g_str_equal (signal_name, "TestSignal"))
+    {
+      GVariant *expected;
+
+      expected = g_variant_parse (NULL, "(1, 2, 3)", NULL, NULL, NULL);
+      g_assert (g_variant_equal (parameters, expected));
+      g_variant_unref (expected);
+
+      signal_was_received = TRUE;
+    }
+}
+
+static void
+test_creation_error (void)
+{
+  /* Sync with 'error' */
+  if (g_test_trap_fork (0, 0))
+    {
+      GError *error = NULL;
+      GVariant *reply;
+
+      g_setenv ("DBUS_SESSION_BUS_ADDRESS", "some nonsense", 1);
+
+      reply = dconf_engine_dbus_call_sync_func (G_BUS_TYPE_SESSION,
+                                                "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetId",
+                                                g_variant_new ("()"), G_VARIANT_TYPE ("(as)"), &error);
+
+      g_assert (reply == NULL);
+      g_assert (error != NULL);
+      g_assert (strstr (error->message, "some nonsense"));
+      exit (0);
+    }
+
+  g_test_trap_assert_passed ();
+
+  /* Sync without 'error' */
+  if (g_test_trap_fork (0, 0))
+    {
+      GVariant *reply;
+
+      g_setenv ("DBUS_SESSION_BUS_ADDRESS", "some nonsense", 1);
+
+      reply = dconf_engine_dbus_call_sync_func (G_BUS_TYPE_SESSION,
+                                                "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetId",
+                                                g_variant_new ("()"), G_VARIANT_TYPE ("(as)"), NULL);
+
+      g_assert (reply == NULL);
+      exit (0);
+    }
+
+  g_test_trap_assert_passed ();
+
+  /* Async */
+  if (g_test_trap_fork (0, 0))
+    {
+      DConfEngineCallHandle *handle;
+      GError *error = NULL;
+      gboolean success;
+
+      g_setenv ("DBUS_SESSION_BUS_ADDRESS", "some nonsense", 1);
+
+      handle = g_malloc (1);
+
+      g_mutex_lock (&async_call_queue_lock);
+      g_queue_push_tail (&async_call_error_queue, handle);
+      g_mutex_unlock (&async_call_queue_lock);
+
+      success = dconf_engine_dbus_call_async_func (G_BUS_TYPE_SESSION,
+                                                   "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetId",
+                                                   g_variant_new ("()"), handle, &error);
+
+      /* This could either fail immediately or asynchronously, depending
+       * on how the backend is setup.
+       */
+      if (success)
+        {
+          g_assert_no_error (error);
+
+          g_mutex_lock (&async_call_queue_lock);
+          while (!g_queue_is_empty (&async_call_error_queue))
+            g_cond_wait (&async_call_queue_cond, &async_call_queue_lock);
+          g_mutex_unlock (&async_call_queue_lock);
+        }
+      else
+        g_assert (error != NULL);
+
+      exit (0);
+    }
+
+  g_test_trap_assert_passed ();
+}
+
+static void
+test_sync_call_success (void)
+{
+  GError *error = NULL;
+  gchar *session_id;
+  gchar *system_id;
+  GVariant *reply;
+
+  reply = dconf_engine_dbus_call_sync_func (G_BUS_TYPE_SESSION,
+                                            "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListNames",
+                                            g_variant_new ("()"), G_VARIANT_TYPE ("(as)"), &error);
+
+  g_assert_no_error (error);
+  g_assert (reply != NULL);
+  g_assert (g_variant_is_of_type (reply, G_VARIANT_TYPE ("(as)")));
+  g_variant_unref (reply);
+
+  reply = dconf_engine_dbus_call_sync_func (G_BUS_TYPE_SESSION,
+                                            "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetId",
+                                            g_variant_new ("()"), G_VARIANT_TYPE ("(s)"), &error);
+
+  g_assert_no_error (error);
+  g_assert (reply != NULL);
+  g_assert (g_variant_is_of_type (reply, G_VARIANT_TYPE ("(s)")));
+  g_variant_get (reply, "(s)", &session_id);
+  g_variant_unref (reply);
+
+  reply = dconf_engine_dbus_call_sync_func (G_BUS_TYPE_SYSTEM,
+                                            "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetId",
+                                            g_variant_new ("()"), G_VARIANT_TYPE ("(s)"), &error);
+
+  g_assert_no_error (error);
+  g_assert (reply != NULL);
+  g_assert (g_variant_is_of_type (reply, G_VARIANT_TYPE ("(s)")));
+  g_variant_get (reply, "(s)", &system_id);
+  g_variant_unref (reply);
+
+  /* Make sure we actually saw two separate buses */
+  g_assert_cmpstr (session_id, !=, system_id);
+  g_free (session_id);
+  g_free (system_id);
+}
+
+static void
+test_sync_call_error (void)
+{
+  GError *error = NULL;
+  GVariant *reply;
+
+  /* Test receiving errors from the other side */
+  reply = dconf_engine_dbus_call_sync_func (G_BUS_TYPE_SESSION,
+                                            "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetId",
+                                            g_variant_new ("(u)", 1), G_VARIANT_TYPE_UNIT, &error);
+  g_assert (reply == NULL);
+  g_assert (error != NULL);
+  g_assert (strstr (error->message, "org.freedesktop.DBus.Error.InvalidArgs"));
+  g_clear_error (&error);
+
+  /* Test reply type errors */
+  reply = dconf_engine_dbus_call_sync_func (G_BUS_TYPE_SESSION,
+                                            "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetId",
+                                            g_variant_new ("()"), G_VARIANT_TYPE ("(u)"), &error);
+  g_assert (reply == NULL);
+  g_assert (error != NULL);
+  g_assert (strstr (error->message, " type "));
+  g_clear_error (&error);
+}
+
+static void
+test_async_call_success (void)
+{
+  gint i;
+
+  for (i = 0; i < 1000; i++)
+    {
+      DConfEngineCallHandle *handle;
+      GError *error = NULL;
+      gboolean success;
+
+      handle = g_malloc (1);
+      g_mutex_lock (&async_call_queue_lock);
+      g_queue_push_tail (&async_call_success_queue, handle);
+      g_mutex_unlock (&async_call_queue_lock);
+
+      success = dconf_engine_dbus_call_async_func (G_BUS_TYPE_SESSION,
+                                                   "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetId",
+                                                   g_variant_new ("()"), handle, &error);
+      g_assert_no_error (error);
+      g_assert (success);
+    }
+
+  g_mutex_lock (&async_call_queue_lock);
+  while (!g_queue_is_empty (&async_call_success_queue))
+    g_cond_wait (&async_call_queue_cond, &async_call_queue_lock);
+  g_mutex_unlock (&async_call_queue_lock);
+}
+
+static void
+test_async_call_error (void)
+{
+  DConfEngineCallHandle *handle;
+  GError *error = NULL;
+  gboolean success;
+
+  handle = g_malloc (1);
+
+  g_mutex_lock (&async_call_queue_lock);
+  g_queue_push_tail (&async_call_error_queue, handle);
+  g_mutex_unlock (&async_call_queue_lock);
+
+  success = dconf_engine_dbus_call_async_func (G_BUS_TYPE_SESSION,
+                                               "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetId",
+                                               g_variant_new ("(u)", 4), handle, &error);
+  g_assert_no_error (error);
+  g_assert (success);
+
+  g_mutex_lock (&async_call_queue_lock);
+  while (!g_queue_is_empty (&async_call_error_queue))
+    g_cond_wait (&async_call_queue_cond, &async_call_queue_lock);
+  g_mutex_unlock (&async_call_queue_lock);
+}
+
+static void
+test_sync_during_async (void)
+{
+  DConfEngineCallHandle *handle;
+  GError *error = NULL;
+  gboolean success;
+  GVariant *reply;
+
+  handle = g_malloc (1);
+  g_mutex_lock (&async_call_queue_lock);
+  g_queue_push_tail (&async_call_success_queue, handle);
+  g_mutex_unlock (&async_call_queue_lock);
+
+  success = dconf_engine_dbus_call_async_func (G_BUS_TYPE_SESSION,
+                                               "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetId",
+                                               g_variant_new ("()"), handle, &error);
+  g_assert_no_error (error);
+  g_assert (success);
+
+  reply = dconf_engine_dbus_call_sync_func (G_BUS_TYPE_SESSION,
+                                            "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListNames",
+                                            g_variant_new ("()"), G_VARIANT_TYPE ("(as)"), &error);
+  g_assert_no_error (error);
+  g_assert (reply != NULL);
+  g_variant_unref (reply);
+
+  g_mutex_lock (&async_call_queue_lock);
+  while (!g_queue_is_empty (&async_call_success_queue))
+    g_cond_wait (&async_call_queue_cond, &async_call_queue_lock);
+  g_mutex_unlock (&async_call_queue_lock);
+}
+
+static void
+test_signal_receipt (void)
+{
+  GError *error = NULL;
+  GVariant *reply;
+  gint i;
+
+  reply = dconf_engine_dbus_call_sync_func (G_BUS_TYPE_SESSION,
+                                            "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "AddMatch",
+                                            g_variant_new ("(s)", "type='signal',interface='ca.desrt.dconf.Writer'"),
+                                            G_VARIANT_TYPE_UNIT, &error);
+  g_assert_no_error (error);
+  g_assert (reply != NULL);
+  g_variant_unref (reply);
+
+  system ("gdbus emit --session "
+          "--object-path /ca/desrt/dconf/Writer/testcase "
+          "--signal ca.desrt.dconf.Writer.TestSignal "
+          "1 2 3");
+
+  /* total time: 30 seconds */
+  for (i = 0; i < 300; i++)
+    {
+      if (signal_was_received)
+        return;
+
+      g_usleep (100 * G_TIME_SPAN_MILLISECOND);
+    }
+
+  g_assert_not_reached ();
+}
+
+int
+main (int argc, char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+
+  /* XXX should not need to do this here! */
+  g_type_init ();
+
+  main_thread = g_thread_self ();
+
+  /* test_creation_error absolutely must come first */
+  g_test_add_func (DBUS_BACKEND "/creation/error", test_creation_error);
+  g_test_add_func (DBUS_BACKEND "/sync-call/success", test_sync_call_success);
+  g_test_add_func (DBUS_BACKEND "/sync-call/error", test_sync_call_error);
+  g_test_add_func (DBUS_BACKEND "/async-call/success", test_async_call_success);
+  g_test_add_func (DBUS_BACKEND "/async-call/error", test_async_call_error);
+  g_test_add_func (DBUS_BACKEND "/sync-during-async", test_sync_during_async);
+  g_test_add_func (DBUS_BACKEND "/signal-receipt", test_signal_receipt);
+
+  return g_test_run ();
+}



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