Files
wireplumber/tests/wp/component-loader.c
George Kiagiadakis 84d3382292 config: make it possible to have feature profiles
A profile is a list of features set to required/optional/disabled
which governs which components are getting loaded, given a static
components list with well-defined dependencies
2023-06-23 20:15:26 +03:00

241 lines
7.1 KiB
C

/* WirePlumber
*
* Copyright © 2023 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include "../common/base-test-fixture.h"
struct _WpTestPlugin
{
WpPlugin parent;
gboolean enabled;
};
#define WP_TYPE_TEST_PLUGIN (wp_test_plugin_get_type ())
G_DECLARE_FINAL_TYPE (WpTestPlugin, wp_test_plugin, WP, TEST_PLUGIN, WpPlugin)
G_DEFINE_TYPE (WpTestPlugin, wp_test_plugin, WP_TYPE_PLUGIN)
static void
wp_test_plugin_init (WpTestPlugin * self)
{
}
static void
wp_test_plugin_enable (WpPlugin * self, WpTransition * transition)
{
WP_TEST_PLUGIN (self)->enabled = TRUE;
if (g_str_equal (wp_plugin_get_name (self), "fail")) {
wp_transition_return_error (transition, g_error_new (WP_DOMAIN_LIBRARY,
WP_LIBRARY_ERROR_INVALID_ARGUMENT, "fail"));
} else {
wp_object_update_features (WP_OBJECT (self), WP_PLUGIN_FEATURE_ENABLED, 0);
}
}
static void
wp_test_plugin_class_init (WpTestPluginClass * klass)
{
WpPluginClass *pclass = (WpPluginClass *) klass;
pclass->enable = wp_test_plugin_enable;
}
struct _WpTestCompLoader
{
GObject parent;
GPtrArray *history;
};
static void wp_test_comp_loader_iface_init (WpComponentLoaderInterface * iface);
#define WP_TYPE_TEST_COMP_LOADER (wp_test_comp_loader_get_type ())
G_DECLARE_FINAL_TYPE (WpTestCompLoader, wp_test_comp_loader,
WP, TEST_COMP_LOADER, GObject)
G_DEFINE_TYPE_WITH_CODE (WpTestCompLoader, wp_test_comp_loader,
G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (
WP_TYPE_COMPONENT_LOADER,
wp_test_comp_loader_iface_init))
static void
wp_test_comp_loader_init (WpTestCompLoader * self)
{
self->history = g_ptr_array_new_with_free_func (g_free);
}
static void
wp_test_comp_loader_finalize (GObject * self)
{
g_clear_pointer (&WP_TEST_COMP_LOADER (self)->history, g_ptr_array_unref);
G_OBJECT_CLASS (wp_test_comp_loader_parent_class)->finalize (self);
}
static void
wp_test_comp_loader_class_init (WpTestCompLoaderClass * klass)
{
GObjectClass *oclass = (GObjectClass *) klass;
oclass->finalize = wp_test_comp_loader_finalize;
}
static gboolean
wp_test_comp_loader_supports_type (WpComponentLoader * cl, const gchar * type)
{
return g_str_equal (type, "test");
}
static void
wp_test_comp_loader_load (WpComponentLoader * self, WpCore * core,
const gchar * component, const gchar * type, WpSpaJson * args,
GCancellable * cancellable, GAsyncReadyCallback callback, gpointer data)
{
g_autoptr (GTask) task = g_task_new (self, cancellable, callback, data);
GObject *plugin = g_object_new (WP_TYPE_TEST_PLUGIN,
"name", component,
"core", core,
NULL);
g_ptr_array_add (WP_TEST_COMP_LOADER (self)->history, g_strdup (component));
g_task_return_pointer (task, plugin, g_object_unref);
}
static GObject *
wp_test_comp_loader_load_finish (WpComponentLoader * self,
GAsyncResult * res, GError ** error)
{
return g_task_propagate_pointer (G_TASK (res), error);
}
static void
wp_test_comp_loader_iface_init (WpComponentLoaderInterface * iface)
{
iface->supports_type = wp_test_comp_loader_supports_type;
iface->load = wp_test_comp_loader_load;
iface->load_finish = wp_test_comp_loader_load_finish;
}
typedef struct {
WpBaseTestFixture base;
WpTestCompLoader *loader;
} TestFixture;
static void
test_setup (TestFixture *self, gconstpointer user_data)
{
wp_base_test_fixture_setup (&self->base, 0);
self->loader = g_object_new (WP_TYPE_TEST_COMP_LOADER, NULL);
wp_core_register_object (self->base.core, self->loader);
}
static void
test_teardown (TestFixture *self, gconstpointer user_data)
{
wp_base_test_fixture_teardown (&self->base);
}
static void
on_component_loaded (WpCore * core, GAsyncResult * res, TestFixture *f)
{
gboolean loaded;
GError *error = NULL;
loaded = wp_core_load_component_finish (core, res, &error);
g_assert_no_error (error);
g_assert_true (loaded);
g_main_loop_quit (f->base.loop);
}
static void
test_load (TestFixture *f, gconstpointer data)
{
wp_core_load_component (f->base.core, "name123", "test", NULL,
"feature.name123", NULL, (GAsyncReadyCallback) on_component_loaded, f);
g_main_loop_run (f->base.loop);
g_autoptr (WpPlugin) plugin = wp_plugin_find (f->base.core, "name123");
g_assert_nonnull (plugin);
g_assert_true (WP_IS_TEST_PLUGIN (plugin));
g_assert_true (WP_TEST_PLUGIN (plugin)->enabled);
g_assert_true (wp_core_test_feature (f->base.core, "feature.name123"));
}
static void
on_component_failed (WpCore * core, GAsyncResult * res, TestFixture *f)
{
gboolean loaded;
GError *error = NULL;
loaded = wp_core_load_component_finish (core, res, &error);
g_assert_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT);
g_assert_false (loaded);
g_main_loop_quit (f->base.loop);
}
static void
test_load_failure (TestFixture *f, gconstpointer data)
{
wp_core_load_component (f->base.core, "fail", "test", NULL,
"feature.fail", NULL, (GAsyncReadyCallback) on_component_failed, f);
g_main_loop_run (f->base.loop);
g_assert_cmpuint (f->loader->history->len, ==, 1);
g_assert_cmpstr (f->loader->history->pdata[0], ==, "fail");
g_autoptr (WpPlugin) plugin = wp_plugin_find (f->base.core, "fail");
g_assert_null (plugin);
g_assert_false (wp_core_test_feature (f->base.core, "feature.fail"));
}
static void
test_dependencies_setup (TestFixture *f, gconstpointer data)
{
f->base.conf_file =
g_strdup_printf ("%s/component-loader.conf", g_getenv ("G_TEST_SRCDIR"));
test_setup (f, data);
}
static void
test_dependencies (TestFixture *f, gconstpointer data)
{
wp_core_load_component (f->base.core, "test", "profile", NULL,
NULL, NULL, (GAsyncReadyCallback) on_component_loaded, f);
g_main_loop_run (f->base.loop);
// NULL-terminate the array
g_ptr_array_add (f->loader->history, NULL);
/* verify the order of loading the plugins was as expected */
const gchar *expected[] = {
"five", "one", "six", "two", "three", "four", "seven", NULL };
g_assert_cmpstrv (f->loader->history->pdata, expected);
g_assert_true (wp_core_test_feature (f->base.core, "support.one"));
g_assert_true (wp_core_test_feature (f->base.core, "support.two"));
g_assert_true (wp_core_test_feature (f->base.core, "support.three"));
g_assert_true (wp_core_test_feature (f->base.core, "support.four"));
g_assert_true (wp_core_test_feature (f->base.core, "virtual.four"));
g_assert_true (wp_core_test_feature (f->base.core, "support.five"));
g_assert_true (wp_core_test_feature (f->base.core, "support.six"));
g_assert_false (wp_core_test_feature (f->base.core, "support.seven"));
g_assert_false (wp_core_test_feature (f->base.core, "support.eight"));
}
gint
main (gint argc, gchar *argv[])
{
g_test_init (&argc, &argv, NULL);
wp_init (WP_INIT_ALL);
g_test_add ("/wp/comploader/load", TestFixture, NULL,
test_setup, test_load, test_teardown);
g_test_add ("/wp/comploader/load_failure", TestFixture, NULL,
test_setup, test_load_failure, test_teardown);
g_test_add ("/wp/comploader/dependencies", TestFixture, NULL,
test_dependencies_setup, test_dependencies, test_teardown);
return g_test_run ();
}