summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorGarrett Regier <garrett.regier@riftio.com>2014-11-08 12:31:58 -0800
committerGarrett Regier <garrett.regier@riftio.com>2014-11-18 10:30:39 -0800
commit9a2b7a92741fd88fb059882c84eca9381246d554 (patch)
tree3927de976367d3086becc4e8be680c793ee4d69d /tests
parent47ff5e97b4066822b773c04a063914fecafb20bf (diff)
downloadlibpeas-9a2b7a92741fd88fb059882c84eca9381246d554.tar.gz
Add an extension test that uses multiple threads
This should act as a good stress test for checking that libpeas is thread-safe. This also changes testing-utils to be thread aware. https://bugzilla.gnome.org/show_bug.cgi?id=739619
Diffstat (limited to 'tests')
-rw-r--r--tests/libpeas/testing/testing-extension.c62
-rw-r--r--tests/testing-util/testing-util.c92
2 files changed, 131 insertions, 23 deletions
diff --git a/tests/libpeas/testing/testing-extension.c b/tests/libpeas/testing/testing-extension.c
index 2fd5dda..97e7dfc 100644
--- a/tests/libpeas/testing/testing-extension.c
+++ b/tests/libpeas/testing/testing-extension.c
@@ -270,6 +270,64 @@ test_extension_get_settings (PeasEngine *engine,
}
static void
+multiple_threads_in_thread (guint nth_thread)
+{
+ gint i, j;
+ PeasEngine *engine;
+ PeasPluginInfo *info;
+ GObject *extension;
+ const gboolean is_slow = strstr (loader, "python") != NULL;
+
+ engine = testing_engine_new ();
+ peas_engine_enable_loader (engine, loader);
+
+ info = peas_engine_get_plugin_info (engine, extension_plugin);
+ g_assert (info != NULL);
+
+ for (i = 0; i < (is_slow ? 5 : 20); ++i)
+ {
+ g_assert (peas_engine_load_plugin (engine, info));
+
+ for (j = 0; j < 5; ++j)
+ {
+ extension = peas_engine_create_extension (engine, info,
+ INTROSPECTION_TYPE_BASE,
+ NULL);
+
+ g_assert (extension != NULL);
+ g_object_unref (extension);
+ }
+
+ g_assert (peas_engine_unload_plugin (engine, info));
+ }
+
+ testing_engine_free (engine);
+}
+
+static void
+test_extension_multiple_threads (PeasEngine *engine,
+ PeasPluginInfo *info)
+{
+ gint i;
+ GThreadPool *pool;
+ GError *error = NULL;
+ const gboolean is_slow = strstr (loader, "python") != NULL;
+
+ pool = g_thread_pool_new ((GFunc) multiple_threads_in_thread,
+ NULL, g_get_num_processors (), TRUE, &error);
+ g_assert_no_error (error);
+
+ for (i = 0; i < (is_slow ? 20 : 100); ++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);
+}
+
+static void
test_extension_call_no_args (PeasEngine *engine,
PeasPluginInfo *info)
{
@@ -428,6 +486,10 @@ testing_extension_basic (const gchar *loader_)
_EXTENSION_TEST (loader, "plugin-info", plugin_info);
_EXTENSION_TEST (loader, "get-settings", get_settings);
+
+ /* See peas_engine_enable_loader() */
+ if (g_strcmp0 (loader, "lua5.1") != 0)
+ _EXTENSION_TEST (loader, "multiple-threads", multiple_threads);
}
void
diff --git a/tests/testing-util/testing-util.c b/tests/testing-util/testing-util.c
index e67b502..bd0f839 100644
--- a/tests/testing-util/testing-util.c
+++ b/tests/testing-util/testing-util.c
@@ -37,10 +37,17 @@ typedef struct {
gboolean hit;
} LogHook;
-static PeasEngine *engine = NULL;
-static GPtrArray *log_hooks = NULL;
+static void engine_private_notify (gpointer value);
+static void log_hooks_private_notify (gpointer value);
+
static gboolean initialized = FALSE;
+static gpointer dead_engine = NULL;
+#define DEAD_ENGINE ((gpointer) &dead_engine)
+
+static GPrivate engine_key = G_PRIVATE_INIT (engine_private_notify);
+static GPrivate log_hooks_key = G_PRIVATE_INIT (log_hooks_private_notify);
+
/* These are warnings and criticals that just have to happen
* for testing purposes and as such we don't want to abort on them.
*
@@ -55,11 +62,47 @@ static const gchar *allowed_patterns[] = {
};
static void
+engine_private_notify (gpointer value)
+{
+ if (value != NULL)
+ g_error ("A PeasEngine was not freed!");
+}
+
+static void
+log_hooks_private_notify (gpointer value)
+{
+ GPtrArray *log_hooks = value;
+
+ if (log_hooks != NULL)
+ {
+ g_assert_cmpuint (log_hooks->len, ==, 0);
+ g_ptr_array_unref (log_hooks);
+ }
+}
+
+static GPtrArray *
+get_log_hooks (void)
+{
+ GPtrArray *log_hooks = g_private_get (&log_hooks_key);
+
+ if (log_hooks != NULL)
+ return log_hooks;
+
+ g_assert (initialized);
+
+ log_hooks = g_ptr_array_new_with_free_func (g_free);
+ g_private_set (&log_hooks_key, log_hooks);
+
+ return log_hooks;
+}
+
+static void
log_handler (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
+ GPtrArray *log_hooks = get_log_hooks ();
guint i;
/* We always want to log debug, info and message logs */
@@ -148,25 +191,36 @@ testing_util_init (void)
g_irepository_require (g_irepository_get_default (), "Peas", "1.0", 0, &error);
g_assert_no_error (error);
- log_hooks = g_ptr_array_new_with_free_func (g_free);
-
initialized = TRUE;
}
+static void
+engine_weak_notify (gpointer unused,
+ PeasEngine *engine)
+{
+ /* Cannot use NULL because testing_util_engine_free() must be called */
+ g_private_set (&engine_key, DEAD_ENGINE);
+}
+
PeasEngine *
testing_util_engine_new (void)
{
+ PeasEngine *engine;
+
g_assert (initialized);
/* testing_util_engine_free() checks that the
* engine is freed so only one engine can be created
*/
- g_assert (engine == NULL);
+ g_assert (g_private_get (&engine_key) == NULL);
/* Must be after requiring typelibs */
engine = peas_engine_new ();
+ g_private_set (&engine_key, engine);
- g_object_add_weak_pointer (G_OBJECT (engine), (gpointer *) &engine);
+ g_object_weak_ref (G_OBJECT (engine),
+ (GWeakNotify) engine_weak_notify,
+ NULL);
peas_engine_add_search_path (engine, BUILDDIR "/tests/plugins",
SRCDIR "/tests/plugins");
@@ -175,17 +229,19 @@ testing_util_engine_new (void)
}
void
-testing_util_engine_free (PeasEngine *engine_)
+testing_util_engine_free (PeasEngine *engine)
{
/* In case a test needs to free the engine */
- if (engine != NULL)
+ if (g_private_get (&engine_key) != DEAD_ENGINE)
{
- g_object_unref (engine_);
+ g_object_unref (engine);
/* Make sure that at the end of every test the engine is freed */
- g_assert (engine == NULL);
+ g_assert (g_private_get (&engine_key) == DEAD_ENGINE);
}
+ g_private_set (&engine_key, NULL);
+
/* Pop the log hooks so the test cases don't have to */
testing_util_pop_log_hooks ();
}
@@ -199,15 +255,6 @@ testing_util_run_tests (void)
retval = g_test_run ();
- /* Make sure all the engines have been freed */
- g_assert (engine == NULL);
-
- if (log_hooks != NULL)
- {
- g_assert_cmpuint (log_hooks->len, ==, 0);
- g_ptr_array_unref (log_hooks);
- }
-
/* Cannot call this with atexit() because
* gcov does not register that it was called.
*/
@@ -219,9 +266,9 @@ testing_util_run_tests (void)
void
testing_util_push_log_hook (const gchar *pattern)
{
+ GPtrArray *log_hooks = get_log_hooks ();
LogHook *hook;
- g_return_if_fail (log_hooks != NULL);
g_return_if_fail (pattern != NULL && *pattern != '\0');
hook = g_new (LogHook, 1);
@@ -235,9 +282,9 @@ testing_util_push_log_hook (const gchar *pattern)
void
testing_util_pop_log_hook (void)
{
+ GPtrArray *log_hooks = get_log_hooks ();
LogHook *hook;
- g_return_if_fail (log_hooks != NULL);
g_return_if_fail (log_hooks->len > 0);
hook = g_ptr_array_index (log_hooks, log_hooks->len - 1);
@@ -251,12 +298,11 @@ testing_util_pop_log_hook (void)
void
testing_util_pop_log_hooks (void)
{
+ GPtrArray *log_hooks = get_log_hooks ();
guint i;
LogHook *hook;
GPtrArray *unhit_hooks;
- g_return_if_fail (log_hooks != NULL);
-
if (log_hooks->len == 0)
return;