diff options
author | Garrett Regier <garrettregier@gmail.com> | 2015-11-20 19:50:48 -0800 |
---|---|---|
committer | Garrett Regier <garrettregier@gmail.com> | 2015-12-15 16:57:46 -0800 |
commit | b19f1cea0fdc5b91ed6ef6d40ff67f9dcd217eda (patch) | |
tree | 2b3092d0588ca70c087795c3586fd27c5f62dba4 | |
parent | 8327a10b367397462ba680bfa8c7bba334dfbd08 (diff) | |
download | libpeas-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-- | .gitignore | 2 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | docs/reference/libpeas-docs.sgml | 4 | ||||
-rw-r--r-- | docs/reference/libpeas-sections.txt | 2 | ||||
-rw-r--r-- | libpeas/peas-engine.c | 78 | ||||
-rw-r--r-- | libpeas/peas-object-module.c | 122 | ||||
-rw-r--r-- | libpeas/peas-object-module.h | 3 | ||||
-rw-r--r-- | libpeas/peas-plugin-info-priv.h | 1 | ||||
-rw-r--r-- | libpeas/peas-plugin-info.c | 59 | ||||
-rw-r--r-- | libpeas/peas-plugin-loader-c.c | 22 | ||||
-rw-r--r-- | tests/libpeas/Makefile.am | 2 | ||||
-rw-r--r-- | tests/libpeas/extension-c.c | 65 | ||||
-rw-r--r-- | tests/libpeas/plugins/Makefile.am | 2 | ||||
-rw-r--r-- | tests/libpeas/plugins/embedded/Makefile.am | 55 | ||||
-rw-r--r-- | tests/libpeas/plugins/embedded/embedded-invalid-loader.plugin | 8 | ||||
-rw-r--r-- | tests/libpeas/plugins/embedded/embedded-missing-symbol.plugin | 7 | ||||
-rw-r--r-- | tests/libpeas/plugins/embedded/embedded-plugin.c | 135 | ||||
-rw-r--r-- | tests/libpeas/plugins/embedded/embedded-plugin.h | 52 | ||||
-rw-r--r-- | tests/libpeas/plugins/embedded/embedded.gresource.xml | 7 | ||||
-rw-r--r-- | tests/libpeas/plugins/embedded/embedded.plugin | 7 | ||||
-rw-r--r-- | tests/libpeas/testing/testing.c | 19 |
21 files changed, 606 insertions, 47 deletions
@@ -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; } |