mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-23 20:46:14 +01:00
tests: Run GModule tests in subprocesses
While we try to unload the test modules that we load, at the end of each test, it’s not always possible: musl, for example, explicitly doesn’t support unloading modules (see https://wiki.musl-libc.org/functional-differences-from-glibc.html#Unloading_libraries). Signed-off-by: Philip Withnall <pwithnall@gnome.org> Fixes: #3415
This commit is contained in:
parent
435aeddbc7
commit
84fe784b51
@ -77,133 +77,146 @@ static SimpleFunc plugin_clash_func = NULL;
|
|||||||
static void
|
static void
|
||||||
test_module_basics (void)
|
test_module_basics (void)
|
||||||
{
|
{
|
||||||
GModule *module_self, *module_a, *module_b;
|
|
||||||
gchar *plugin_a, *plugin_b;
|
|
||||||
SimpleFunc f_a, f_b, f_self;
|
|
||||||
GModuleFunc gmod_f;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
if (!g_module_supported ())
|
if (!g_module_supported ())
|
||||||
g_error ("dynamic modules not supported");
|
{
|
||||||
|
g_test_skip ("dynamic modules not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
plugin_a = g_test_build_filename (G_TEST_BUILT, MODULE_FILENAME_PREFIX "moduletestplugin_a_" MODULE_TYPE, NULL);
|
/* Run the actual test in a subprocess to avoid symbol table changes from
|
||||||
plugin_b = g_test_build_filename (G_TEST_BUILT, MODULE_FILENAME_PREFIX "moduletestplugin_b_" MODULE_TYPE, NULL);
|
* previous tests potentially affecting it. */
|
||||||
|
if (g_test_subprocess ())
|
||||||
|
{
|
||||||
|
GModule *module_self, *module_a, *module_b;
|
||||||
|
gchar *plugin_a, *plugin_b;
|
||||||
|
SimpleFunc f_a, f_b, f_self;
|
||||||
|
GModuleFunc gmod_f;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
/* module handles */
|
plugin_a = g_test_build_filename (G_TEST_BUILT, MODULE_FILENAME_PREFIX "moduletestplugin_a_" MODULE_TYPE, NULL);
|
||||||
|
plugin_b = g_test_build_filename (G_TEST_BUILT, MODULE_FILENAME_PREFIX "moduletestplugin_b_" MODULE_TYPE, NULL);
|
||||||
|
|
||||||
module_self = g_module_open_full (NULL, G_MODULE_BIND_LAZY, &error);
|
/* module handles */
|
||||||
g_assert_no_error (error);
|
|
||||||
if (!module_self)
|
|
||||||
g_error ("error: %s", g_module_error ());
|
|
||||||
|
|
||||||
/* On Windows static compilation mode, glib API symbols are not
|
module_self = g_module_open_full (NULL, G_MODULE_BIND_LAZY, &error);
|
||||||
* exported dynamically by definition. */
|
g_assert_no_error (error);
|
||||||
|
if (!module_self)
|
||||||
|
g_error ("error: %s", g_module_error ());
|
||||||
|
|
||||||
|
/* On Windows static compilation mode, glib API symbols are not
|
||||||
|
* exported dynamically by definition. */
|
||||||
#if !defined(G_PLATFORM_WIN32) || !defined(GLIB_STATIC_COMPILATION)
|
#if !defined(G_PLATFORM_WIN32) || !defined(GLIB_STATIC_COMPILATION)
|
||||||
if (!g_module_symbol (module_self, "g_module_close", (gpointer *) &f_self))
|
if (!g_module_symbol (module_self, "g_module_close", (gpointer *) &f_self))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
module_a = g_module_open_full (plugin_a, G_MODULE_BIND_LAZY, &error);
|
module_a = g_module_open_full (plugin_a, G_MODULE_BIND_LAZY, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
if (!module_a)
|
if (!module_a)
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
|
|
||||||
module_b = g_module_open_full (plugin_b, G_MODULE_BIND_LAZY, &error);
|
module_b = g_module_open_full (plugin_b, G_MODULE_BIND_LAZY, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
if (!module_b)
|
if (!module_b)
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
|
|
||||||
/* get plugin state vars */
|
/* get plugin state vars */
|
||||||
|
|
||||||
if (!g_module_symbol (module_a, "gplugin_a_state",
|
if (!g_module_symbol (module_a, "gplugin_a_state",
|
||||||
(gpointer *) &gplugin_a_state))
|
(gpointer *) &gplugin_a_state))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
|
|
||||||
if (!g_module_symbol (module_b, "gplugin_b_state",
|
if (!g_module_symbol (module_b, "gplugin_b_state",
|
||||||
(gpointer *) &gplugin_b_state))
|
(gpointer *) &gplugin_b_state))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
test_states (NULL, NULL, "check-init");
|
test_states (NULL, NULL, "check-init");
|
||||||
|
|
||||||
/* get plugin specific symbols and call them */
|
/* get plugin specific symbols and call them */
|
||||||
|
|
||||||
if (!g_module_symbol (module_a, "gplugin_a_func", (gpointer *) &f_a))
|
if (!g_module_symbol (module_a, "gplugin_a_func", (gpointer *) &f_a))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
test_states (NULL, NULL, NULL);
|
test_states (NULL, NULL, NULL);
|
||||||
|
|
||||||
if (!g_module_symbol (module_b, "gplugin_b_func", (gpointer *) &f_b))
|
if (!g_module_symbol (module_b, "gplugin_b_func", (gpointer *) &f_b))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
test_states (NULL, NULL, NULL);
|
test_states (NULL, NULL, NULL);
|
||||||
|
|
||||||
f_a ();
|
f_a ();
|
||||||
test_states (NULL, "Hello world", NULL);
|
test_states (NULL, "Hello world", NULL);
|
||||||
|
|
||||||
f_b ();
|
f_b ();
|
||||||
test_states (NULL, NULL, "Hello world");
|
test_states (NULL, NULL, "Hello world");
|
||||||
|
|
||||||
/* get and call globally clashing functions */
|
/* get and call globally clashing functions */
|
||||||
|
|
||||||
if (!g_module_symbol (module_self, "g_clash_func", (gpointer *) &f_self))
|
if (!g_module_symbol (module_self, "g_clash_func", (gpointer *) &f_self))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
test_states (NULL, NULL, NULL);
|
test_states (NULL, NULL, NULL);
|
||||||
|
|
||||||
if (!g_module_symbol (module_a, "g_clash_func", (gpointer *) &f_a))
|
if (!g_module_symbol (module_a, "g_clash_func", (gpointer *) &f_a))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
test_states (NULL, NULL, NULL);
|
test_states (NULL, NULL, NULL);
|
||||||
|
|
||||||
if (!g_module_symbol (module_b, "g_clash_func", (gpointer *) &f_b))
|
if (!g_module_symbol (module_b, "g_clash_func", (gpointer *) &f_b))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
test_states (NULL, NULL, NULL);
|
test_states (NULL, NULL, NULL);
|
||||||
|
|
||||||
f_self ();
|
f_self ();
|
||||||
test_states ("global clash", NULL, NULL);
|
test_states ("global clash", NULL, NULL);
|
||||||
|
|
||||||
f_a ();
|
f_a ();
|
||||||
test_states (NULL, "global clash", NULL);
|
test_states (NULL, "global clash", NULL);
|
||||||
|
|
||||||
f_b ();
|
f_b ();
|
||||||
test_states (NULL, NULL, "global clash");
|
test_states (NULL, NULL, "global clash");
|
||||||
|
|
||||||
/* get and call clashing plugin functions */
|
/* get and call clashing plugin functions */
|
||||||
|
|
||||||
if (!g_module_symbol (module_a, "gplugin_clash_func", (gpointer *) &f_a))
|
if (!g_module_symbol (module_a, "gplugin_clash_func", (gpointer *) &f_a))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
test_states (NULL, NULL, NULL);
|
test_states (NULL, NULL, NULL);
|
||||||
|
|
||||||
if (!g_module_symbol (module_b, "gplugin_clash_func", (gpointer *) &f_b))
|
if (!g_module_symbol (module_b, "gplugin_clash_func", (gpointer *) &f_b))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
test_states (NULL, NULL, NULL);
|
test_states (NULL, NULL, NULL);
|
||||||
|
|
||||||
plugin_clash_func = f_a;
|
plugin_clash_func = f_a;
|
||||||
plugin_clash_func ();
|
plugin_clash_func ();
|
||||||
test_states (NULL, "plugin clash", NULL);
|
test_states (NULL, "plugin clash", NULL);
|
||||||
|
|
||||||
plugin_clash_func = f_b;
|
plugin_clash_func = f_b;
|
||||||
plugin_clash_func ();
|
plugin_clash_func ();
|
||||||
test_states (NULL, NULL, "plugin clash");
|
test_states (NULL, NULL, "plugin clash");
|
||||||
|
|
||||||
/* call gmodule function from A */
|
/* call gmodule function from A */
|
||||||
|
|
||||||
if (!g_module_symbol (module_a, "gplugin_a_module_func", (gpointer *) &gmod_f))
|
if (!g_module_symbol (module_a, "gplugin_a_module_func", (gpointer *) &gmod_f))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
test_states (NULL, NULL, NULL);
|
test_states (NULL, NULL, NULL);
|
||||||
|
|
||||||
gmod_f (module_b);
|
gmod_f (module_b);
|
||||||
test_states (NULL, NULL, "BOOH");
|
test_states (NULL, NULL, "BOOH");
|
||||||
|
|
||||||
gmod_f (module_a);
|
gmod_f (module_a);
|
||||||
test_states (NULL, "BOOH", NULL);
|
test_states (NULL, "BOOH", NULL);
|
||||||
|
|
||||||
/* unload plugins */
|
/* unload plugins */
|
||||||
|
|
||||||
if (!g_module_close (module_a))
|
if (!g_module_close (module_a))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
|
|
||||||
if (!g_module_close (module_b))
|
if (!g_module_close (module_b))
|
||||||
g_error ("error: %s", g_module_error ());
|
g_error ("error: %s", g_module_error ());
|
||||||
|
|
||||||
g_free (plugin_a);
|
g_free (plugin_a);
|
||||||
g_free (plugin_b);
|
g_free (plugin_b);
|
||||||
g_module_close (module_self);
|
g_module_close (module_self);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
|
||||||
|
g_test_trap_assert_passed ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -236,13 +249,6 @@ test_module_invalid_libtool_archive (void)
|
|||||||
static void
|
static void
|
||||||
test_local_binding (void)
|
test_local_binding (void)
|
||||||
{
|
{
|
||||||
gchar *plugin = NULL;
|
|
||||||
GModule *module_plugin = NULL, *module_self = NULL;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
gboolean found_symbol = FALSE;
|
|
||||||
gpointer symbol = NULL;
|
|
||||||
|
|
||||||
g_test_summary ("Test that binding a library's symbols locally does not add them globally");
|
g_test_summary ("Test that binding a library's symbols locally does not add them globally");
|
||||||
|
|
||||||
#if defined(G_PLATFORM_WIN32)
|
#if defined(G_PLATFORM_WIN32)
|
||||||
@ -250,23 +256,40 @@ test_local_binding (void)
|
|||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
plugin = g_test_build_filename (G_TEST_BUILT, MODULE_FILENAME_PREFIX "moduletestplugin_a_" MODULE_TYPE, NULL);
|
/* Run the actual test in a subprocess to avoid symbol table changes from
|
||||||
|
* previous tests potentially affecting it. */
|
||||||
|
if (g_test_subprocess ())
|
||||||
|
{
|
||||||
|
gchar *plugin = NULL;
|
||||||
|
GModule *module_plugin = NULL, *module_self = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
module_plugin = g_module_open_full (plugin, G_MODULE_BIND_LOCAL, &error);
|
gboolean found_symbol = FALSE;
|
||||||
g_assert_no_error (error);
|
gpointer symbol = NULL;
|
||||||
g_assert_nonnull (module_plugin);
|
|
||||||
|
|
||||||
module_self = g_module_open_full (NULL, 0, &error);
|
plugin = g_test_build_filename (G_TEST_BUILT, MODULE_FILENAME_PREFIX "moduletestplugin_a_" MODULE_TYPE, NULL);
|
||||||
g_assert_no_error (error);
|
|
||||||
g_assert_nonnull (module_self);
|
|
||||||
|
|
||||||
found_symbol = g_module_symbol (module_self, "gplugin_say_boo_func", &symbol);
|
module_plugin = g_module_open_full (plugin, G_MODULE_BIND_LOCAL, &error);
|
||||||
g_assert_false (found_symbol);
|
g_assert_no_error (error);
|
||||||
g_assert_null (symbol);
|
g_assert_nonnull (module_plugin);
|
||||||
|
|
||||||
g_module_close (module_self);
|
module_self = g_module_open_full (NULL, 0, &error);
|
||||||
g_module_close (module_plugin);
|
g_assert_no_error (error);
|
||||||
g_free (plugin);
|
g_assert_nonnull (module_self);
|
||||||
|
|
||||||
|
found_symbol = g_module_symbol (module_self, "gplugin_say_boo_func", &symbol);
|
||||||
|
g_assert_false (found_symbol);
|
||||||
|
g_assert_null (symbol);
|
||||||
|
|
||||||
|
g_module_close (module_self);
|
||||||
|
g_module_close (module_plugin);
|
||||||
|
g_free (plugin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
|
||||||
|
g_test_trap_assert_passed ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
Loading…
Reference in New Issue
Block a user