[libpeas] Test that plugins are multi-thread safe



commit 8265675b1cafc2f4a259060bf2035aab921ff596
Author: Garrett Regier <garrett regier riftio com>
Date:   Tue Dec 16 02:31:42 2014 -0800

    Test that plugins are multi-thread safe
    
    https://bugzilla.gnome.org/show_bug.cgi?id=741579

 .../plugins/extension-lua/extension-lua51.lua      |   10 ++
 .../plugins/extension-python/extension-py.py.in    |   15 +++-
 tests/libpeas/testing/testing-extension.c          |   98 ++++++++++++++------
 3 files changed, 92 insertions(+), 31 deletions(-)
---
diff --git a/tests/libpeas/plugins/extension-lua/extension-lua51.lua 
b/tests/libpeas/plugins/extension-lua/extension-lua51.lua
index 409aa7c..cca6ee7 100644
--- a/tests/libpeas/plugins/extension-lua/extension-lua51.lua
+++ b/tests/libpeas/plugins/extension-lua/extension-lua51.lua
@@ -18,6 +18,15 @@ ExtensionLuaPlugin._property.object =
                             { GObject.ParamFlags.READABLE,
                               GObject.ParamFlags.WRITABLE })
 
+ExtensionLuaPlugin._property.update_count =
+    GObject.ParamSpecInt('update-count', 'update-count', 'update-count',
+                         0, 1000000, 0,
+                         { GObject.ParamFlags.READABLE })
+
+function ExtensionLuaPlugin:_init()
+    self.priv.update_count = 0
+end
+
 function ExtensionLuaPlugin:do_activate()
     collectgarbage('restart')
 end
@@ -27,6 +36,7 @@ function ExtensionLuaPlugin:do_deactivate()
 end
 
 function ExtensionLuaPlugin:do_update_state()
+    self.priv.update_count = self.priv.update_count + 1
 end
 
 function ExtensionLuaPlugin:do_get_plugin_info()
diff --git a/tests/libpeas/plugins/extension-python/extension-py.py.in 
b/tests/libpeas/plugins/extension-python/extension-py.py.in
index 0a3f613..063ac56 100644
--- a/tests/libpeas/plugins/extension-python/extension-py.py.in
+++ b/tests/libpeas/plugins/extension-python/extension-py.py.in
@@ -1,14 +1,25 @@
 # -*- coding: utf-8 -*-
 # ex:set ts=4 et sw=4 ai:
 
+import threading
+
 from gi.repository import GObject, Introspection, Peas
 
+
 class ExtensionPythonPlugin(GObject.Object, Peas.Activatable,
                             Introspection.Base, Introspection.Callable,
                             Introspection.HasPrerequisite):
 
     object = GObject.property(type=GObject.Object)
 
+    @GObject.property(type=int)
+    def update_count(self):
+        return self.__update_count
+
+    def __init__(self):
+        self.__lock = threading.Lock()
+        self.__update_count = 0
+
     def do_activate(self):
         pass
 
@@ -16,7 +27,8 @@ class ExtensionPythonPlugin(GObject.Object, Peas.Activatable,
         pass
 
     def do_update_state(self):
-        pass
+        with self.__lock:
+            self.__update_count += 1
 
     def do_get_plugin_info(self):
         return self.plugin_info
@@ -35,3 +47,4 @@ class ExtensionPythonPlugin(GObject.Object, Peas.Activatable,
 
     def do_call_multi_args(self, in_, inout):
         return (inout, in_)
+
diff --git a/tests/libpeas/testing/testing-extension.c b/tests/libpeas/testing/testing-extension.c
index 51fb2e6..21077df 100644
--- a/tests/libpeas/testing/testing-extension.c
+++ b/tests/libpeas/testing/testing-extension.c
@@ -269,9 +269,35 @@ test_extension_get_settings (PeasEngine     *engine,
   g_object_unref (extension);
 }
 
+static gint
+run_in_multiple_threads (GFunc    func,
+                         gpointer user_data)
+{
+  gint i, n_threads;
+  GThreadPool *pool;
+  GError *error = NULL;
+
+  /* Avoid too many threads, but try to get some good contention */
+  n_threads = g_get_num_processors () + 2;
+
+  pool = g_thread_pool_new (func, user_data, n_threads, TRUE, &error);
+  g_assert_no_error (error);
+
+  for (i = 0; i < n_threads; ++i)
+    {
+      /* Cannot supply NULL as the data... */
+      g_thread_pool_push (pool, GUINT_TO_POINTER (i + 1), &error);
+      g_assert_no_error (error);
+    }
+
+  g_thread_pool_free (pool, FALSE, TRUE);
+
+  return n_threads;
+}
+
 static void
-multiple_threads_in_thread (guint    nth_thread,
-                            gboolean use_nonglobal_loaders)
+multiple_threads_loaders_in_thread (guint    nth_thread,
+                                    gboolean use_nonglobal_loaders)
 {
   gint i, j;
   PeasEngine *engine;
@@ -305,44 +331,49 @@ multiple_threads_in_thread (guint    nth_thread,
 }
 
 static void
-test_extension_multiple_threads (PeasEngine     *engine,
-                                 PeasPluginInfo *info,
-                                 gboolean        use_nonglobal_loaders)
+test_extension_multiple_threads_global_loaders (PeasEngine     *engine,
+                                                PeasPluginInfo *info)
 {
-  gint i, n_threads;
-  GThreadPool *pool;
-  GError *error = NULL;
-
-  /* Avoid too many threads, but try to get some good contention */
-  n_threads = g_get_num_processors () + 2;
-
-  pool = g_thread_pool_new ((GFunc) multiple_threads_in_thread,
-                            GINT_TO_POINTER (use_nonglobal_loaders),
-                            n_threads, TRUE, &error);
-  g_assert_no_error (error);
-
-  for (i = 0; i < g_thread_pool_get_max_threads (pool); ++i)
-    {
-      /* Cannot supply NULL as the data... */
-      g_thread_pool_push (pool, GUINT_TO_POINTER (i + 1), &error);
-      g_assert_no_error (error);
-    }
+  run_in_multiple_threads ((GFunc) multiple_threads_loaders_in_thread,
+                           GINT_TO_POINTER (FALSE));
+}
 
-  g_thread_pool_free (pool, FALSE, TRUE);
+static void
+test_extension_multiple_threads_nonglobal_loaders (PeasEngine     *engine,
+                                                   PeasPluginInfo *info)
+{
+  run_in_multiple_threads ((GFunc) multiple_threads_loaders_in_thread,
+                           GINT_TO_POINTER (TRUE));
 }
 
 static void
-test_extension_multiple_threads_global_loaders (PeasEngine     *engine,
-                                                PeasPluginInfo *info)
+multiple_threads_callbacks_in_thread (guint            nth_thread,
+                                      PeasActivatable *activatable)
 {
-  test_extension_multiple_threads (engine, info, FALSE);
+  gint i;
+
+  for (i = 0; i < 100; ++i)
+    peas_activatable_update_state (activatable);
 }
 
 static void
-test_extension_multiple_threads_nonglobal_loaders (PeasEngine     *engine,
-                                                   PeasPluginInfo *info)
+test_extension_multiple_threads_callbacks (PeasEngine     *engine,
+                                           PeasPluginInfo *info)
 {
-  test_extension_multiple_threads (engine, info, TRUE);
+  PeasExtension *extension;
+  gint n_threads, update_count;
+
+  extension = peas_engine_create_extension (engine, info,
+                                            PEAS_TYPE_ACTIVATABLE,
+                                            NULL);
+
+  n_threads = run_in_multiple_threads ((GFunc) multiple_threads_callbacks_in_thread,
+                                       extension);
+
+  g_object_get (extension, "update-count", &update_count, NULL);
+  g_assert_cmpint (update_count, ==, n_threads * 100);
+
+  g_object_unref (extension);
 }
 
 static void
@@ -509,6 +540,13 @@ testing_extension_basic (const gchar *loader_)
                    multiple_threads_global_loaders);
   _EXTENSION_TEST (loader, "multiple-threads/nonglobal-loaders",
                    multiple_threads_nonglobal_loaders);
+
+  /* Not needed for C plugins as they are independent of libpeas */
+  if (g_strcmp0 (loader, "c") != 0)
+    {
+      _EXTENSION_TEST (loader, "multiple-threads/callbacks",
+                       multiple_threads_callbacks);
+    }
 }
 
 void


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