summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Regier <garrettregier@gmail.com>2015-11-20 19:50:48 -0800
committerGarrett Regier <garrettregier@gmail.com>2015-12-15 16:57:46 -0800
commitb19f1cea0fdc5b91ed6ef6d40ff67f9dcd217eda (patch)
tree2b3092d0588ca70c087795c3586fd27c5f62dba4
parent8327a10b367397462ba680bfa8c7bba334dfbd08 (diff)
downloadlibpeas-b19f1cea0fdc5b91ed6ef6d40ff67f9dcd217eda.tar.gz
Add support for embedded C plugins
This adds the new key Embedded to the .plugin file which specifies the function to call instead of peas_register_types to perform that same job. https://bugzilla.gnome.org/show_bug.cgi?id=721693
-rw-r--r--.gitignore2
-rw-r--r--configure.ac1
-rw-r--r--docs/reference/libpeas-docs.sgml4
-rw-r--r--docs/reference/libpeas-sections.txt2
-rw-r--r--libpeas/peas-engine.c78
-rw-r--r--libpeas/peas-object-module.c122
-rw-r--r--libpeas/peas-object-module.h3
-rw-r--r--libpeas/peas-plugin-info-priv.h1
-rw-r--r--libpeas/peas-plugin-info.c59
-rw-r--r--libpeas/peas-plugin-loader-c.c22
-rw-r--r--tests/libpeas/Makefile.am2
-rw-r--r--tests/libpeas/extension-c.c65
-rw-r--r--tests/libpeas/plugins/Makefile.am2
-rw-r--r--tests/libpeas/plugins/embedded/Makefile.am55
-rw-r--r--tests/libpeas/plugins/embedded/embedded-invalid-loader.plugin8
-rw-r--r--tests/libpeas/plugins/embedded/embedded-missing-symbol.plugin7
-rw-r--r--tests/libpeas/plugins/embedded/embedded-plugin.c135
-rw-r--r--tests/libpeas/plugins/embedded/embedded-plugin.h52
-rw-r--r--tests/libpeas/plugins/embedded/embedded.gresource.xml7
-rw-r--r--tests/libpeas/plugins/embedded/embedded.plugin7
-rw-r--r--tests/libpeas/testing/testing.c19
21 files changed, 606 insertions, 47 deletions
diff --git a/.gitignore b/.gitignore
index a8aba8f..73a8b4d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -87,6 +87,8 @@ Makefile.in
/tests/libpeas/extension-python3
/tests/libpeas/extension-set
/tests/libpeas/plugin-info
+/tests/libpeas/plugins/embedded/embedded-resources.c
+/tests/libpeas/plugins/embedded/embedded-resources.h
/tests/libpeas/plugins/extension-python/extension-python.gschema.xml
/tests/libpeas/plugins/extension-python/extension-python.plugin
/tests/libpeas/plugins/extension-python/extension-python.py
diff --git a/configure.ac b/configure.ac
index c838361..6a7028d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -556,6 +556,7 @@ po/Makefile.in
tests/Makefile
tests/libpeas/Makefile
tests/libpeas/plugins/Makefile
+tests/libpeas/plugins/embedded/Makefile
tests/libpeas/plugins/extension-c/Makefile
tests/libpeas/plugins/extension-lua/Makefile
tests/libpeas/plugins/extension-python/Makefile
diff --git a/docs/reference/libpeas-docs.sgml b/docs/reference/libpeas-docs.sgml
index 44e5c5f..0e96245 100644
--- a/docs/reference/libpeas-docs.sgml
+++ b/docs/reference/libpeas-docs.sgml
@@ -59,6 +59,10 @@
<title>Index of new symbols in 1.14</title>
<xi:include href="xml/api-index-1.14.xml"><xi:fallback /></xi:include>
</index>
+ <index id="api-index-1-18" role="1.18">
+ <title>Index of new symbols in 1.18</title>
+ <xi:include href="xml/api-index-1.18.xml"><xi:fallback /></xi:include>
+ </index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>
diff --git a/docs/reference/libpeas-sections.txt b/docs/reference/libpeas-sections.txt
index ff80d31..610a163 100644
--- a/docs/reference/libpeas-sections.txt
+++ b/docs/reference/libpeas-sections.txt
@@ -152,10 +152,12 @@ PEAS_OBJECT_MODULE_GET_CLASS
PeasObjectModulePrivate
peas_object_module_new
peas_object_module_new_full
+peas_object_module_new_embedded
peas_object_module_create_object
peas_object_module_get_library
peas_object_module_get_module_name
peas_object_module_get_path
+peas_object_module_get_symbol
peas_object_module_provides_object
</SECTION>
diff --git a/libpeas/peas-engine.c b/libpeas/peas-engine.c
index 4a2782b..ccee8a6 100644
--- a/libpeas/peas-engine.c
+++ b/libpeas/peas-engine.c
@@ -161,10 +161,10 @@ load_plugin_info (PeasEngine *engine,
}
static void
-load_dir_real (PeasEngine *engine,
- const gchar *module_dir,
- const gchar *data_dir,
- guint recursions)
+load_file_dir_real (PeasEngine *engine,
+ const gchar *module_dir,
+ const gchar *data_dir,
+ guint recursions)
{
GError *error = NULL;
GDir *d;
@@ -188,7 +188,7 @@ load_dir_real (PeasEngine *engine,
if (g_file_test (filename, G_FILE_TEST_IS_DIR))
{
if (recursions > 0)
- load_dir_real (engine, filename, data_dir, recursions - 1);
+ load_file_dir_real (engine, filename, data_dir, recursions - 1);
}
else if (g_str_has_suffix (dirent, ".plugin"))
{
@@ -201,6 +201,67 @@ load_dir_real (PeasEngine *engine,
g_dir_close (d);
}
+static void
+load_resource_dir_real (PeasEngine *engine,
+ const gchar *module_dir,
+ const gchar *data_dir,
+ guint recursions)
+{
+ guint i;
+ const gchar *module_path;
+ gchar **children;
+ GError *error = NULL;
+
+ g_debug ("Loading %s/*.plugin...", module_dir);
+
+ module_path = module_dir + strlen ("resource://");
+ children = g_resources_enumerate_children (module_path,
+ G_RESOURCE_LOOKUP_FLAGS_NONE,
+ &error);
+
+ if (error != NULL)
+ {
+ g_debug ("%s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ for (i = 0; children[i] != NULL; ++i)
+ {
+ gboolean is_dir;
+ gchar *child;
+
+ is_dir = g_str_has_suffix (children[i], "/");
+
+ if (is_dir && recursions == 0)
+ continue;
+
+ if (!is_dir && !g_str_has_suffix (children[i], ".plugin"))
+ continue;
+
+ child = g_build_path ("/", module_dir, children[i], NULL);
+
+ if (is_dir)
+ load_resource_dir_real (engine, child, data_dir, recursions - 1);
+ else
+ load_plugin_info (engine, child, module_dir, data_dir);
+
+ g_free (child);
+ }
+
+ g_strfreev (children);
+}
+
+static void
+load_dir_real (PeasEngine *engine,
+ SearchPath *sp)
+{
+ if (!g_str_has_prefix (sp->module_dir, "resource://"))
+ load_file_dir_real (engine, sp->module_dir, sp->data_dir, 1);
+ else
+ load_resource_dir_real (engine, sp->module_dir, sp->data_dir, 1);
+}
+
/**
* peas_engine_rescan_plugins:
* @engine: A #PeasEngine.
@@ -229,10 +290,7 @@ peas_engine_rescan_plugins (PeasEngine *engine)
/* Go and read everything from the provided search paths */
for (item = priv->search_paths; item != NULL; item = item->next)
- {
- SearchPath *sp = (SearchPath *) item->data;
- load_dir_real (engine, sp->module_dir, sp->data_dir, 1);
- }
+ load_dir_real (engine, (SearchPath *) item->data);
g_object_thaw_notify (G_OBJECT (engine));
}
@@ -256,7 +314,7 @@ peas_engine_insert_search_path (PeasEngine *engine,
priv->search_paths = g_list_insert (priv->search_paths, sp, position);
g_object_freeze_notify (G_OBJECT (engine));
- load_dir_real (engine, sp->module_dir, sp->data_dir, 1);
+ load_dir_real (engine, sp);
g_object_thaw_notify (G_OBJECT (engine));
}
diff --git a/libpeas/peas-object-module.c b/libpeas/peas-object-module.c
index a6ae729..fbd81f2 100644
--- a/libpeas/peas-object-module.c
+++ b/libpeas/peas-object-module.c
@@ -48,6 +48,7 @@ enum {
PROP_0,
PROP_MODULE_NAME,
PROP_PATH,
+ PROP_SYMBOL,
PROP_RESIDENT,
PROP_LOCAL_LINKAGE,
N_PROPERTIES
@@ -70,6 +71,7 @@ struct _PeasObjectModulePrivate {
gchar *path;
gchar *module_name;
+ gchar *symbol;
guint resident : 1;
guint local_linkage : 1;
@@ -91,27 +93,39 @@ peas_object_module_load (GTypeModule *gmodule)
{
PeasObjectModule *module = PEAS_OBJECT_MODULE (gmodule);
PeasObjectModulePrivate *priv = GET_PRIV (module);
- GModuleFlags flags = 0;
- gchar *path;
-
- if (priv->local_linkage)
- flags = G_MODULE_BIND_LOCAL;
- path = g_module_build_path (priv->path, priv->module_name);
- g_return_val_if_fail (path != NULL, FALSE);
+ g_return_val_if_fail (priv->module_name != NULL, FALSE);
- /* g_module_build_path() will add G_MODULE_SUFFIX to the path,
- * however g_module_open() will only try to load the libtool archive
- * if there is no suffix specified. So we remove G_MODULE_SUFFIX here
- * which allows uninstalled builds to load plugins as well, as there
- * is only the .la file in the build directory.
- */
- if (G_MODULE_SUFFIX[0] != '\0' && g_str_has_suffix (path, "." G_MODULE_SUFFIX))
- path[strlen (path) - strlen (G_MODULE_SUFFIX) - 1] = '\0';
+ if (priv->path == NULL)
+ {
+ g_return_val_if_fail (priv->resident, FALSE);
+ g_return_val_if_fail (!priv->local_linkage, FALSE);
- /* Bind symbols immediately to avoid errors long after loading */
- priv->library = g_module_open (path, flags);
- g_free (path);
+ priv->library = g_module_open (NULL, 0);
+ }
+ else
+ {
+ gchar *path;
+ GModuleFlags flags = 0;
+
+ path = g_module_build_path (priv->path, priv->module_name);
+
+ /* g_module_build_path() will add G_MODULE_SUFFIX to the path,
+ * however g_module_open() will only try to load the libtool archive
+ * if there is no suffix specified. So we remove G_MODULE_SUFFIX here
+ * which allows uninstalled builds to load plugins as well, as there
+ * is only the .la file in the build directory.
+ */
+ if (G_MODULE_SUFFIX[0] != '\0' && g_str_has_suffix (path, "." G_MODULE_SUFFIX))
+ path[strlen (path) - strlen (G_MODULE_SUFFIX) - 1] = '\0';
+
+ if (priv->local_linkage)
+ flags = G_MODULE_BIND_LOCAL;
+
+ /* Bind symbols immediately to avoid errors long after loading */
+ priv->library = g_module_open (path, flags);
+ g_free (path);
+ }
if (priv->library == NULL)
{
@@ -122,12 +136,11 @@ peas_object_module_load (GTypeModule *gmodule)
}
/* Extract the required symbol from the library */
- if (!g_module_symbol (priv->library,
- "peas_register_types",
+ if (!g_module_symbol (priv->library, priv->symbol,
(gpointer) &priv->register_func))
{
- g_warning ("Failed to get 'peas_register_types' for module '%s': %s",
- priv->module_name, g_module_error ());
+ g_warning ("Failed to get '%s' for module '%s': %s",
+ priv->symbol, priv->module_name, g_module_error ());
g_module_close (priv->library);
return FALSE;
@@ -138,8 +151,8 @@ peas_object_module_load (GTypeModule *gmodule)
*/
if (priv->register_func == NULL)
{
- g_warning ("Invalid 'peas_register_types' in module '%s'",
- priv->module_name);
+ g_warning ("Invalid '%s' in module '%s'",
+ priv->symbol, priv->module_name);
g_module_close (priv->library);
return FALSE;
@@ -194,6 +207,7 @@ peas_object_module_finalize (GObject *object)
g_free (priv->path);
g_free (priv->module_name);
+ g_free (priv->symbol);
g_array_unref (priv->implementations);
G_OBJECT_CLASS (peas_object_module_parent_class)->finalize (object);
@@ -216,6 +230,9 @@ peas_object_module_get_property (GObject *object,
case PROP_PATH:
g_value_set_string (value, priv->path);
break;
+ case PROP_SYMBOL:
+ g_value_set_string (value, priv->symbol);
+ break;
case PROP_RESIDENT:
g_value_set_boolean (value, priv->resident);
break;
@@ -247,6 +264,9 @@ peas_object_module_set_property (GObject *object,
case PROP_PATH:
priv->path = g_value_dup_string (value);
break;
+ case PROP_SYMBOL:
+ priv->symbol = g_value_dup_string (value);
+ break;
case PROP_RESIDENT:
priv->resident = g_value_get_boolean (value);
break;
@@ -292,6 +312,15 @@ peas_object_module_class_init (PeasObjectModuleClass *klass)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
+ properties[PROP_SYMBOL] =
+ g_param_spec_string ("symbol",
+ "Symbol",
+ "The registration symbol to use for this module",
+ "peas_register_types",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
properties[PROP_RESIDENT] =
g_param_spec_boolean ("resident",
"Resident",
@@ -377,6 +406,31 @@ peas_object_module_new_full (const gchar *module_name,
}
/**
+ * peas_object_module_new_embedded: (skip)
+ * @module_name: The module name.
+ *
+ * Creates a new #PeasObjectModule for an embedded plugin.
+ *
+ * Return value: a new #PeasObjectModule.
+ *
+ * Since: 1.18
+ */
+PeasObjectModule *
+peas_object_module_new_embedded (const gchar *module_name,
+ const gchar *symbol)
+{
+ g_return_val_if_fail (module_name != NULL && *module_name != '\0', NULL);
+ g_return_val_if_fail (symbol != NULL && *symbol != '\0', NULL);
+
+ return PEAS_OBJECT_MODULE (g_object_new (PEAS_TYPE_OBJECT_MODULE,
+ "module-name", module_name,
+ "symbol", symbol,
+ "resident", TRUE,
+ "local-linkage", FALSE,
+ NULL));
+}
+
+/**
* peas_object_module_create_object: (skip)
* @module: A #PeasObjectModule.
* @interface: The #GType of the extension interface.
@@ -484,6 +538,26 @@ peas_object_module_get_module_name (PeasObjectModule *module)
}
/**
+ * peas_object_module_get_symbol: (skip)
+ * @module: A #PeasObjectModule.
+ *
+ * Gets the symbol name used to register extension implementations.
+ *
+ * Return value: the symbol name.
+ *
+ * Since: 1.18
+ */
+const gchar *
+peas_object_module_get_symbol (PeasObjectModule *module)
+{
+ PeasObjectModulePrivate *priv = GET_PRIV (module);
+
+ g_return_val_if_fail (PEAS_IS_OBJECT_MODULE (module), NULL);
+
+ return priv->symbol;
+}
+
+/**
* peas_object_module_get_library: (skip)
* @module: A #PeasObjectModule.
*
diff --git a/libpeas/peas-object-module.h b/libpeas/peas-object-module.h
index 9f7e164..70a0265 100644
--- a/libpeas/peas-object-module.h
+++ b/libpeas/peas-object-module.h
@@ -91,6 +91,8 @@ PeasObjectModule *peas_object_module_new_full (const gchar
const gchar *path,
gboolean resident,
gboolean local_linkage);
+PeasObjectModule *peas_object_module_new_embedded (const gchar *module_name,
+ const gchar *symbol);
GObject *peas_object_module_create_object (PeasObjectModule *module,
GType interface,
@@ -101,6 +103,7 @@ gboolean peas_object_module_provides_object (PeasObjectModule
const gchar *peas_object_module_get_path (PeasObjectModule *module);
const gchar *peas_object_module_get_module_name (PeasObjectModule *module);
+const gchar *peas_object_module_get_symbol (PeasObjectModule *module);
GModule *peas_object_module_get_library (PeasObjectModule *module);
diff --git a/libpeas/peas-plugin-info-priv.h b/libpeas/peas-plugin-info-priv.h
index e4b2fd3..2359df5 100644
--- a/libpeas/peas-plugin-info-priv.h
+++ b/libpeas/peas-plugin-info-priv.h
@@ -37,6 +37,7 @@ struct _PeasPluginInfo {
gchar *data_dir;
gint loader_id;
+ gchar *embedded;
gchar *module_name;
gchar **dependencies;
diff --git a/libpeas/peas-plugin-info.c b/libpeas/peas-plugin-info.c
index b30e82b..6fb7ce6 100644
--- a/libpeas/peas-plugin-info.c
+++ b/libpeas/peas-plugin-info.c
@@ -85,6 +85,7 @@ _peas_plugin_info_unref (PeasPluginInfo *info)
g_free (info->filename);
g_free (info->module_dir);
g_free (info->data_dir);
+ g_free (info->embedded);
g_free (info->module_name);
g_strfreev (info->dependencies);
g_free (info->name);
@@ -124,19 +125,42 @@ _peas_plugin_info_new (const gchar *filename,
const gchar *data_dir)
{
gsize i;
+ gboolean is_resource;
gchar *loader = NULL;
gchar **strv, **keys;
PeasPluginInfo *info;
GKeyFile *plugin_file;
+ GBytes *bytes = NULL;
GError *error = NULL;
g_return_val_if_fail (filename != NULL, NULL);
+ is_resource = g_str_has_prefix (filename, "resource://");
+
info = g_new0 (PeasPluginInfo, 1);
info->refcount = 1;
plugin_file = g_key_file_new ();
- if (!g_key_file_load_from_file (plugin_file, filename,
+
+ if (is_resource)
+ {
+ bytes = g_resources_lookup_data (filename + strlen ("resource://"),
+ G_RESOURCE_LOOKUP_FLAGS_NONE,
+ &error);
+ }
+ else
+ {
+ gchar *content;
+ gsize length;
+
+ if (g_file_get_contents (filename, &content, &length, &error))
+ bytes = g_bytes_new_take (content, length);
+ }
+
+ if (bytes == NULL ||
+ !g_key_file_load_from_data (plugin_file,
+ g_bytes_get_data (bytes, NULL),
+ g_bytes_get_size (bytes),
G_KEY_FILE_NONE, &error))
{
g_warning ("Bad plugin file '%s': %s", filename, error->message);
@@ -183,7 +207,31 @@ _peas_plugin_info_new (const gchar *filename,
}
}
- g_free (loader);
+ /* Get Embedded */
+ info->embedded = g_key_file_get_string (plugin_file, "Plugin",
+ "Embedded", NULL);
+ if (info->embedded != NULL)
+ {
+ if (info->loader_id != PEAS_UTILS_C_LOADER_ID)
+ {
+ g_warning ("Bad plugin file '%s': embedded plugins "
+ "must use the C plugin loader", filename);
+ goto error;
+ }
+
+ if (!is_resource)
+ {
+ g_warning ("Bad plugin file '%s': embedded plugins "
+ "must be a resource", filename);
+ goto error;
+ }
+ }
+ else if (is_resource)
+ {
+ g_warning ("Bad plugin file '%s': resource plugins must be embedded",
+ filename);
+ goto error;
+ }
/* Get the dependency list */
info->dependencies = g_key_file_get_string_list (plugin_file,
@@ -259,11 +307,14 @@ _peas_plugin_info_new (const gchar *filename,
g_strfreev (keys);
+ g_free (loader);
+ g_bytes_unref (bytes);
g_key_file_free (plugin_file);
info->filename = g_strdup (filename);
info->module_dir = g_strdup (module_dir);
- info->data_dir = g_build_filename (data_dir, info->module_name, NULL);
+ info->data_dir = g_build_path (is_resource ? "/" : G_DIR_SEPARATOR_S,
+ data_dir, info->module_name, NULL);
/* If we know nothing about the availability of the plugin,
set it as available */
@@ -273,10 +324,12 @@ _peas_plugin_info_new (const gchar *filename,
error:
+ g_free (info->embedded);
g_free (loader);
g_free (info->module_name);
g_free (info->name);
g_free (info);
+ g_clear_pointer (&bytes, g_bytes_unref);
g_key_file_free (plugin_file);
return NULL;
diff --git a/libpeas/peas-plugin-loader-c.c b/libpeas/peas-plugin-loader-c.c
index 59942d0..a476eb4 100644
--- a/libpeas/peas-plugin-loader-c.c
+++ b/libpeas/peas-plugin-loader-c.c
@@ -65,13 +65,21 @@ peas_plugin_loader_c_load (PeasPluginLoader *loader,
module_name = peas_plugin_info_get_module_name (info);
module_dir = peas_plugin_info_get_module_dir (info);
- /* Force all C modules to be resident in case they
- * use libraries that do not deal well with reloading.
- * Furthermore, we use local linkage to improve module isolation.
- */
- info->loader_data = peas_object_module_new_full (module_name,
- module_dir,
- TRUE, TRUE);
+ if (info->embedded != NULL)
+ {
+ info->loader_data = peas_object_module_new_embedded (module_name,
+ info->embedded);
+ }
+ else
+ {
+ /* Force all C modules to be resident in case they
+ * use libraries that do not deal well with reloading.
+ * Furthermore, we use local linkage to improve module isolation.
+ */
+ info->loader_data = peas_object_module_new_full (module_name,
+ module_dir,
+ TRUE, TRUE);
+ }
if (!g_type_module_use (G_TYPE_MODULE (info->loader_data)))
g_clear_object (&info->loader_data);
diff --git a/tests/libpeas/Makefile.am b/tests/libpeas/Makefile.am
index 6d6696f..fd55197 100644
--- a/tests/libpeas/Makefile.am
+++ b/tests/libpeas/Makefile.am
@@ -25,6 +25,8 @@ TEST_PROGS += \
extension-set \
plugin-info
+extension_c_LDADD = $(LDADD) $(builddir)/plugins/embedded/libembedded.la
+
if ENABLE_LUA51
TEST_PROGS += extension-lua51
extension_lua51_SOURCES = extension-lua.c
diff --git a/tests/libpeas/extension-c.c b/tests/libpeas/extension-c.c
index 05ea14d..4b6834c 100644
--- a/tests/libpeas/extension-c.c
+++ b/tests/libpeas/extension-c.c
@@ -24,9 +24,69 @@
#endif
#include "libpeas/peas.h"
+#include "libpeas/peas-plugin-info-priv.h"
#include "testing/testing-extension.h"
#include "introspection/introspection-base.h"
+#include "plugins/embedded/embedded-plugin.h"
+#include "plugins/embedded/embedded-resources.h"
+
+
+static void
+test_extension_c_embedded (PeasEngine *engine)
+{
+ PeasPluginInfo *info;
+ PeasExtension *extension;
+
+ info = peas_engine_get_plugin_info (engine, "embedded");
+
+ /* Check that the various data is correct */
+ g_assert (!peas_plugin_info_is_loaded (info));
+ g_assert (peas_plugin_info_is_available (info, NULL));
+ g_assert (!peas_plugin_info_is_builtin (info));
+ g_assert (!peas_plugin_info_is_hidden (info));
+ g_assert_cmpstr (peas_plugin_info_get_module_name (info), ==, "embedded");
+ g_assert_cmpstr (peas_plugin_info_get_module_dir (info), ==,
+ "resource:///org/gnome/libpeas/tests/plugins");
+ g_assert_cmpstr (peas_plugin_info_get_data_dir (info), ==,
+ "resource:///org/gnome/libpeas/tests/plugins/embedded");
+ g_assert_cmpstr (info->embedded, ==,
+ "testing_embedded_plugin_register_types");
+
+ /* Check that we can load and unload the plugin multiple times */
+ g_assert (peas_engine_load_plugin (engine, info));
+ g_assert (peas_plugin_info_is_loaded (info));
+ g_assert (peas_engine_load_plugin (engine, info));
+ g_assert (peas_plugin_info_is_loaded (info));
+ g_assert (peas_engine_unload_plugin (engine, info));
+ g_assert (!peas_plugin_info_is_loaded (info));
+ g_assert (peas_engine_unload_plugin (engine, info));
+ g_assert (!peas_plugin_info_is_loaded (info));
+ g_assert (peas_engine_load_plugin (engine, info));
+ g_assert (peas_plugin_info_is_loaded (info));
+
+ extension = peas_engine_create_extension (engine, info,
+ PEAS_TYPE_ACTIVATABLE,
+ NULL);
+
+ g_assert (TESTING_IS_EMBEDDED_PLUGIN (extension));
+
+ g_object_unref (extension);
+}
+
+static void
+test_extension_c_embedded_missing_symbol (PeasEngine *engine)
+{
+ PeasPluginInfo *info;
+
+ testing_util_push_log_hook ("Failed to get '*does_not_exist*' "
+ "for module 'embedded-missing-symbol':*");
+ testing_util_push_log_hook ("Error loading plugin 'embedded-missing-symbol'");
+
+ info = peas_engine_get_plugin_info (engine, "embedded-missing-symbol");
+
+ g_assert (!peas_engine_load_plugin (engine, info));
+}
static void
test_extension_c_instance_refcount (PeasEngine *engine,
@@ -120,6 +180,9 @@ main (int argc,
{
testing_init (&argc, &argv);
+ /* Automatic resource registration has issues here */
+ embedded_register_resource ();
+
/* Only test the basics */
testing_extension_basic ("c");
@@ -128,6 +191,8 @@ main (int argc,
*/
testing_extension_callable ("c");
+ EXTENSION_TEST (c, "embedded", embedded);
+ EXTENSION_TEST (c, "embedded-missing-symbol", embedded_missing_symbol);
EXTENSION_TEST (c, "instance-refcount", instance_refcount);
EXTENSION_TEST (c, "nonexistent", nonexistent);
EXTENSION_TEST (c, "local-linkage", local_linkage);
diff --git a/tests/libpeas/plugins/Makefile.am b/tests/libpeas/plugins/Makefile.am
index 2dfddb2..5db17a9 100644
--- a/tests/libpeas/plugins/Makefile.am
+++ b/tests/libpeas/plugins/Makefile.am
@@ -1,6 +1,6 @@
include $(top_srcdir)/tests/Makefile.plugin
-SUBDIRS = extension-c
+SUBDIRS = embedded extension-c
if ENABLE_LUA51
SUBDIRS += extension-lua
diff --git a/tests/libpeas/plugins/embedded/Makefile.am b/tests/libpeas/plugins/embedded/Makefile.am
new file mode 100644
index 0000000..1123d79
--- /dev/null
+++ b/tests/libpeas/plugins/embedded/Makefile.am
@@ -0,0 +1,55 @@
+include $(top_srcdir)/tests/Makefile.plugin
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ $(PEAS_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(DISABLE_DEPRECATED)
+
+noinst_LTLIBRARIES = libembedded.la
+
+libembedded_la_SOURCES = \
+ embedded-plugin.c \
+ embedded-plugin.h \
+ embedded-resources.c \
+ embedded-resources.h
+
+libembedded_la_LIBADD = \
+ $(PEAS_LIBS) \
+ $(top_builddir)/libpeas/libpeas-1.0.la
+
+embedded_resources_deps = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir "$(srcdir)" --generate-dependencies "$(srcdir)/embedded.gresource.xml")
+embedded_resources_c_deps = $(srcdir)/embedded.gresource.xml $(embedded_resources_deps)
+
+embedded-resources.h: $(embedded_resources_c_deps)
+ $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) \
+ --target="$@" \
+ --sourcedir="$(srcdir)" \
+ --generate \
+ --c-name="embedded" \
+ --manual-register \
+ --internal \
+ "$(srcdir)/embedded.gresource.xml"
+
+embedded-resources.c: $(embedded_resources_c_deps) embedded-resources.h
+ $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) \
+ --target="$@" \
+ --sourcedir="$(srcdir)" \
+ --generate \
+ --c-name="embedded" \
+ --manual-register \
+ --internal \
+ "$(srcdir)/embedded.gresource.xml"
+
+noinst_PLUGIN = \
+ embedded.gresource.xml \
+ embedded.plugin \
+ embedded-invalid-loader.plugin \
+ embedded-missing-symbol.plugin
+
+EXTRA_DIST = $(noinst_PLUGIN)
+
+CLEANFILES = \
+ embedded-resources.c \
+ embedded-resources.h
+
diff --git a/tests/libpeas/plugins/embedded/embedded-invalid-loader.plugin b/tests/libpeas/plugins/embedded/embedded-invalid-loader.plugin
new file mode 100644
index 0000000..413e663
--- /dev/null
+++ b/tests/libpeas/plugins/embedded/embedded-invalid-loader.plugin
@@ -0,0 +1,8 @@
+[Plugin]
+Module=embedded-invalid-loader
+Embedded=peas_engine_new
+Loader=python
+Name=Embedded Invalid Loader
+Description=This plugin is embedded with an invalid loader.
+Authors=Garrett Regier
+Copyright=Copyright © 2015 Garrett Regier
diff --git a/tests/libpeas/plugins/embedded/embedded-missing-symbol.plugin b/tests/libpeas/plugins/embedded/embedded-missing-symbol.plugin
new file mode 100644
index 0000000..7b04c23
--- /dev/null
+++ b/tests/libpeas/plugins/embedded/embedded-missing-symbol.plugin
@@ -0,0 +1,7 @@
+[Plugin]
+Module=embedded-missing-symbol
+Embedded=embedded_missing_symbol__this_symbol_does_not_exist__register_types
+Name=Embedded Missing Symbol
+Description=This plugin is embedded with a missing symbol.
+Authors=Garrett Regier
+Copyright=Copyright © 2015 Garrett Regier
diff --git a/tests/libpeas/plugins/embedded/embedded-plugin.c b/tests/libpeas/plugins/embedded/embedded-plugin.c
new file mode 100644
index 0000000..945d6f4
--- /dev/null
+++ b/tests/libpeas/plugins/embedded/embedded-plugin.c
@@ -0,0 +1,135 @@
+/*
+ * embedded-plugin.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2015 - Garrett Regier
+ *
+ * libpeas 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.
+ *
+ * libpeas 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib-object.h>
+
+#include <libpeas/peas.h>
+
+#include "embedded-plugin.h"
+
+typedef struct {
+ GObject *object;
+} TestingEmbeddedPluginPrivate;
+
+static void peas_activatable_iface_init (PeasActivatableInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (TestingEmbeddedPlugin,
+ testing_embedded_plugin,
+ PEAS_TYPE_EXTENSION_BASE,
+ 0,
+ G_ADD_PRIVATE (TestingEmbeddedPlugin)
+ G_IMPLEMENT_INTERFACE (PEAS_TYPE_ACTIVATABLE,
+ peas_activatable_iface_init))
+
+#define GET_PRIV(o) \
+ (testing_embedded_plugin_get_instance_private (o))
+
+enum {
+ PROP_0,
+ PROP_OBJECT
+};
+
+static void
+testing_embedded_plugin_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TestingEmbeddedPlugin *plugin = TESTING_EMBEDDED_PLUGIN (object);
+ TestingEmbeddedPluginPrivate *priv = GET_PRIV (plugin);
+
+ switch (prop_id)
+ {
+ case PROP_OBJECT:
+ priv->object = g_value_get_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+testing_embedded_plugin_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TestingEmbeddedPlugin *plugin = TESTING_EMBEDDED_PLUGIN (object);
+ TestingEmbeddedPluginPrivate *priv = GET_PRIV (plugin);
+
+ switch (prop_id)
+ {
+ case PROP_OBJECT:
+ g_value_set_object (value, priv->object);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+testing_embedded_plugin_init (TestingEmbeddedPlugin *plugin)
+{
+}
+
+static void
+testing_embedded_plugin_activate (PeasActivatable *activatable)
+{
+}
+
+static void
+testing_embedded_plugin_deactivate (PeasActivatable *activatable)
+{
+}
+
+static void
+testing_embedded_plugin_class_init (TestingEmbeddedPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = testing_embedded_plugin_set_property;
+ object_class->get_property = testing_embedded_plugin_get_property;
+
+ g_object_class_override_property (object_class, PROP_OBJECT, "object");
+}
+
+static void
+peas_activatable_iface_init (PeasActivatableInterface *iface)
+{
+ iface->activate = testing_embedded_plugin_activate;
+ iface->deactivate = testing_embedded_plugin_deactivate;
+}
+
+G_MODULE_EXPORT void
+testing_embedded_plugin_register_types (PeasObjectModule *module)
+{
+ peas_object_module_register_extension_type (module,
+ PEAS_TYPE_ACTIVATABLE,
+ TESTING_TYPE_EMBEDDED_PLUGIN);
+}
diff --git a/tests/libpeas/plugins/embedded/embedded-plugin.h b/tests/libpeas/plugins/embedded/embedded-plugin.h
new file mode 100644
index 0000000..b4111e5
--- /dev/null
+++ b/tests/libpeas/plugins/embedded/embedded-plugin.h
@@ -0,0 +1,52 @@
+/*
+ * embedded-plugin.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2015 - Garrett Regier
+ *
+ * libpeas 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.
+ *
+ * libpeas 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __TESTING_EMBEDDED_PLUGIN_H__
+#define __TESTING_EMBEDDED_PLUGIN_H__
+
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+#define TESTING_TYPE_EMBEDDED_PLUGIN (testing_embedded_plugin_get_type ())
+#define TESTING_EMBEDDED_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TESTING_TYPE_EMBEDDED_PLUGIN, TestingEmbeddedPlugin))
+#define TESTING_EMBEDDED_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TESTING_TYPE_EMBEDDED_PLUGIN, TestingEmbeddedPlugin))
+#define TESTING_IS_EMBEDDED_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TESTING_TYPE_EMBEDDED_PLUGIN))
+#define TESTING_IS_EMBEDDED_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TESTING_TYPE_EMBEDDED_PLUGIN))
+#define TESTING_EMBEDDED_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TESTING_TYPE_EMBEDDED_PLUGIN, TestingEmbeddedPluginClass))
+
+typedef struct _TestingEmbeddedPlugin TestingEmbeddedPlugin;
+typedef struct _TestingEmbeddedPluginClass TestingEmbeddedPluginClass;
+
+struct _TestingEmbeddedPlugin {
+ PeasExtensionBase parent_instance;
+};
+
+struct _TestingEmbeddedPluginClass {
+ PeasExtensionBaseClass parent_class;
+};
+
+GType testing_embedded_plugin_get_type (void) G_GNUC_CONST;
+G_MODULE_EXPORT void testing_embedded_plugin_register_types (PeasObjectModule *module);
+
+G_END_DECLS
+
+#endif /* __TESTING_EMBEDDED_PLUGIN_H__ */
diff --git a/tests/libpeas/plugins/embedded/embedded.gresource.xml b/tests/libpeas/plugins/embedded/embedded.gresource.xml
new file mode 100644
index 0000000..e141934
--- /dev/null
+++ b/tests/libpeas/plugins/embedded/embedded.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/libpeas/tests/plugins">
+ <file>embedded.plugin</file>
+ <file>embedded-missing-symbol.plugin</file>
+ </gresource>
+</gresources>
diff --git a/tests/libpeas/plugins/embedded/embedded.plugin b/tests/libpeas/plugins/embedded/embedded.plugin
new file mode 100644
index 0000000..13563bd
--- /dev/null
+++ b/tests/libpeas/plugins/embedded/embedded.plugin
@@ -0,0 +1,7 @@
+[Plugin]
+Module=embedded
+Embedded=testing_embedded_plugin_register_types
+Name=Embedded
+Description=A plugin that is embedded.
+Authors=Garrett Regier
+Copyright=Copyright © 2015 Garrett Regier
diff --git a/tests/libpeas/testing/testing.c b/tests/libpeas/testing/testing.c
index f71aec1..1d06dcd 100644
--- a/tests/libpeas/testing/testing.c
+++ b/tests/libpeas/testing/testing.c
@@ -76,10 +76,25 @@ testing_engine_new_full (gboolean nonglobal_loaders)
"*unkown-loader.plugin* does-not-exist");
testing_util_push_log_hook ("*Error loading *unkown-loader.plugin*");
+ testing_util_push_log_hook ("Bad plugin file '"
+ BUILDDIR "*/embedded*.plugin': "
+ "embedded plugins must be a resource");
+ testing_util_push_log_hook ("Error loading '"
+ BUILDDIR "*/embedded*.plugin'*");
+
+ testing_util_push_log_hook ("Bad plugin file '"
+ BUILDDIR "*embedded-invalid-loader.plugin': "
+ "embedded plugins must use the C plugin loader");
+
/* Must be after pushing log hooks */
engine = testing_util_engine_new_full (nonglobal_loaders);
- peas_engine_add_search_path (engine, BUILDDIR "/tests/libpeas/plugins",
- SRCDIR "/tests/libpeas/plugins");
+
+ peas_engine_add_search_path (engine,
+ "resource:///org/gnome/libpeas/"
+ "tests/plugins", NULL);
+ peas_engine_add_search_path (engine,
+ BUILDDIR "/tests/libpeas/plugins",
+ SRCDIR "/tests/libpeas/plugins");
return engine;
}