tests: Add tests for WpSettings object
- settings.c tests conf file loading & parsing, metadata updates, wpsetttings object creation and its API. - settings.lua tests the API from lua scripts. - Add a sample settings.conf file, this file contains sections copied over from client.conf along with the settings section. Add a file each for wp side and lua side of scripts. - Make changes in base test infrastructure to take a custom conf file. - Enhance the wp_settings_get_instance_api() to be take metadata_name parameter. So, Wpsetttings is now a singleton instance for a given metadata file. - Enhance the m-settings module also to be take metadata_name parameter. this is handy for lua side of tests as its cumbersome to do this is lua.
This commit is contained in:

committed by
Julian Bouzas

parent
8fd8b01b7a
commit
4d7ce2292e
@@ -15,13 +15,13 @@
|
||||
#include "log.h"
|
||||
#include "private/registry.h"
|
||||
|
||||
/*! \defgroup WpSettings */
|
||||
/*! \defgroup wpsetttings WpSettings */
|
||||
/*!
|
||||
* \struct WpSettings
|
||||
*
|
||||
* WpSettings parses `sm-settings` metadata(contains wireplumber settings
|
||||
* and rules), provides APIs to its clients(modules, lua scripts etc) to
|
||||
* access and change them.
|
||||
* WpSettings loads and parses `sm-settings`(default value) metadata(contains
|
||||
* wireplumber settings and rules). It provides APIs to its clients(modules,
|
||||
* lua scripts etc) to access and change them.
|
||||
*
|
||||
* Being a WpObject subclass, the settings inherits WpObject's activation
|
||||
* system.
|
||||
@@ -32,10 +32,17 @@ struct _WpSettings
|
||||
{
|
||||
WpObject parent;
|
||||
|
||||
GWeakRef core;
|
||||
gchar *metadata_name;
|
||||
|
||||
WpProperties *settings;
|
||||
WpObjectManager *metadata_om;
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_METADATA_NAME,
|
||||
PROP_PROPERTIES,
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (WpSettings, wp_settings, WP_TYPE_OBJECT)
|
||||
@@ -52,13 +59,17 @@ wp_settings_init (WpSettings * self)
|
||||
* \ingroup wpsetting
|
||||
* \param self the handle
|
||||
* \param setting name of the setting
|
||||
* \returns (transfer none): boolean value of the string.
|
||||
* \returns: (transfer none) boolean value of the string.
|
||||
*/
|
||||
gboolean wp_settings_get_boolean (WpSettings *self, const gchar *setting)
|
||||
{
|
||||
g_return_val_if_fail (self, false);
|
||||
g_return_val_if_fail (setting, false);
|
||||
|
||||
if (!(wp_object_get_active_features (WP_OBJECT (self)) &
|
||||
WP_OBJECT_FEATURES_ALL))
|
||||
return false;
|
||||
|
||||
return spa_atob (wp_properties_get (self->settings, setting));
|
||||
}
|
||||
|
||||
@@ -70,7 +81,6 @@ gboolean wp_settings_get_boolean (WpSettings *self, const gchar *setting)
|
||||
*
|
||||
* \ingroup wpsetting
|
||||
* \param self the handle
|
||||
* \param setting name of the setting
|
||||
* \param rule name of the rule, this will match with the section mentioned
|
||||
* in the conf file.
|
||||
* \param client_props client props array, these properties are inputs on which
|
||||
@@ -108,6 +118,19 @@ wp_settings_activate_get_next_step (WpObject * object,
|
||||
return STEP_LOAD;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean check_metadata_name (gpointer g_object,
|
||||
gpointer metadata_name)
|
||||
{
|
||||
if (!WP_IS_SETTINGS(g_object))
|
||||
return false;
|
||||
|
||||
g_auto (GValue) value = G_VALUE_INIT;
|
||||
g_object_get_property (G_OBJECT(g_object), "metadata-name", &value);
|
||||
|
||||
return g_str_equal (g_value_get_string (&value), (gchar *)metadata_name);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Returns the wpsettings instance that is associated with the
|
||||
@@ -116,25 +139,35 @@ wp_settings_activate_get_next_step (WpObject * object,
|
||||
* This method will also create the instance and register it with the core
|
||||
* if it had not been created before.
|
||||
*
|
||||
* \ingroup wpsetting
|
||||
* \param core the core
|
||||
* \return (transfer full): the wpsettings instance
|
||||
* \param metadata_name (nullable) the name of the metadata with which this
|
||||
* object should is associated. `sm-settings` is the default value picked if
|
||||
* none is supplied.
|
||||
* \returns: (transfer full) the wpsettings instance
|
||||
*/
|
||||
WpSettings *
|
||||
wp_settings_get_instance (WpCore * core)
|
||||
wp_settings_get_instance (WpCore *core, const gchar *metadata_name)
|
||||
{
|
||||
WpRegistry *registry = wp_core_get_registry (core);
|
||||
const gchar *name = (metadata_name ? metadata_name : "sm-settings") ;
|
||||
WpSettings *settings = wp_registry_find_object (registry,
|
||||
(GEqualFunc) WP_IS_SETTINGS, NULL);
|
||||
(GEqualFunc) check_metadata_name, name);
|
||||
|
||||
if (G_UNLIKELY (!settings)) {
|
||||
settings = g_object_new (WP_TYPE_SETTINGS,
|
||||
"core", core,
|
||||
"metadata-name", name,
|
||||
NULL);
|
||||
g_weak_ref_set (&settings->core, core);
|
||||
|
||||
wp_registry_register_object (registry, g_object_ref (settings));
|
||||
}
|
||||
|
||||
wp_debug_object (settings, "created wpsettings object for metadata"
|
||||
" name \"%s\"", name);
|
||||
} else {
|
||||
wp_debug_object (settings, "found this wpsettings object for metadata name"
|
||||
" \"%s\"", name);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -153,8 +186,8 @@ on_metadata_added (WpObjectManager *om, WpMetadata *m, gpointer d)
|
||||
wp_debug_object (self, "%s(%lu) = %s", setting, strlen(value), value);
|
||||
}
|
||||
|
||||
wp_info_object (self, "loaded %d settings from metadata",
|
||||
wp_properties_get_count (self->settings));
|
||||
wp_info_object (self, "loaded %d settings from metadata \"%s\"",
|
||||
wp_properties_get_count (self->settings), self->metadata_name);
|
||||
|
||||
wp_object_update_features (WP_OBJECT (self), WP_SETTINGS_LOADED, 0);
|
||||
}
|
||||
@@ -175,13 +208,15 @@ wp_settings_activate_execute_step (WpObject * object,
|
||||
self->metadata_om = wp_object_manager_new ();
|
||||
wp_object_manager_add_interest (self->metadata_om, WP_TYPE_METADATA,
|
||||
WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY, "metadata.name", "=s",
|
||||
"sm-settings", NULL);
|
||||
self->metadata_name, NULL);
|
||||
wp_object_manager_request_object_features (self->metadata_om,
|
||||
WP_TYPE_METADATA, WP_OBJECT_FEATURES_ALL);
|
||||
g_signal_connect_object (self->metadata_om, "object-added",
|
||||
G_CALLBACK (on_metadata_added), transition, 0);
|
||||
wp_core_install_object_manager (core, self->metadata_om);
|
||||
|
||||
wp_debug_object (self, "looking for metadata object named %s",
|
||||
self->metadata_name);
|
||||
break;
|
||||
}
|
||||
case WP_TRANSITION_STEP_ERROR:
|
||||
@@ -196,19 +231,62 @@ wp_settings_deactivate (WpObject * object, WpObjectFeatures features)
|
||||
{
|
||||
WpSettings *self = WP_SETTINGS (object);
|
||||
|
||||
g_free (self->metadata_name);
|
||||
g_clear_pointer (&self->settings, wp_properties_unref);
|
||||
g_clear_object (&self->metadata_om);
|
||||
|
||||
wp_object_update_features (WP_OBJECT (self), 0, WP_OBJECT_FEATURES_ALL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
wp_settings_set_property (GObject * object, guint property_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpSettings *self = WP_SETTINGS (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_METADATA_NAME:
|
||||
self->metadata_name = g_strdup (g_value_get_string (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_settings_get_property (GObject * object, guint property_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpSettings *self = WP_SETTINGS (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_METADATA_NAME:
|
||||
g_value_set_string (value, self->metadata_name);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_settings_class_init (WpSettingsClass * klass)
|
||||
{
|
||||
GObjectClass * object_class = (GObjectClass *) klass;
|
||||
WpObjectClass * wpobject_class = (WpObjectClass *) klass;
|
||||
|
||||
object_class->set_property = wp_settings_set_property;
|
||||
object_class->get_property = wp_settings_get_property;
|
||||
|
||||
wpobject_class->activate_get_next_step = wp_settings_activate_get_next_step;
|
||||
wpobject_class->activate_execute_step = wp_settings_activate_execute_step;
|
||||
wpobject_class->deactivate = wp_settings_deactivate;
|
||||
wpobject_class->get_supported_features = wp_settings_get_supported_features;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_METADATA_NAME,
|
||||
g_param_spec_string ("metadata-name", "metadata-name",
|
||||
"The metadata object to look after", NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ G_DECLARE_FINAL_TYPE (WpSettings, wp_settings, WP, SETTINGS, WpObject)
|
||||
|
||||
WP_API
|
||||
WpSettings *
|
||||
wp_settings_get_instance (WpCore * core);
|
||||
wp_settings_get_instance (WpCore * core, const gchar *metadata_name);
|
||||
|
||||
WP_API
|
||||
gboolean wp_settings_get_boolean (WpSettings *self, const gchar *setting);
|
||||
|
@@ -1472,11 +1472,17 @@ impl_module_new (lua_State *L)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
get_setting (lua_State *L)
|
||||
static gboolean
|
||||
get_boolean (lua_State *L)
|
||||
{
|
||||
const char *setting = luaL_checkstring (L, 1);
|
||||
WpSettings *s = wp_settings_get_instance (get_wp_core (L));
|
||||
const char *metadata_name = NULL;
|
||||
|
||||
if (lua_type (L, 2) == LUA_TSTRING)
|
||||
metadata_name = luaL_checkstring (L, 2);
|
||||
|
||||
WpSettings *s = wp_settings_get_instance (get_wp_core (L), metadata_name);
|
||||
|
||||
if (s)
|
||||
{
|
||||
gboolean value = wp_settings_get_boolean (s, setting);
|
||||
@@ -1488,7 +1494,7 @@ get_setting (lua_State *L)
|
||||
}
|
||||
|
||||
static const luaL_Reg settings_methods[] = {
|
||||
{ "get_setting", get_setting },
|
||||
{ "get_boolean", get_boolean },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@@ -14,8 +14,8 @@
|
||||
/*
|
||||
* This module parses the "wireplumber.settings" section from the .conf file.
|
||||
*
|
||||
* Creates "sm-settings" metadata and pushes the settings to it. Looks out for
|
||||
* changes done in the metadata via the pw-metadata interface.
|
||||
* Creates "sm-settings"(default) metadata and pushes the settings to it.
|
||||
* Looks out for changes done in the metadata via the pw-metadata interface.
|
||||
*
|
||||
* If persistent settings is enabled stores the settings in a state file
|
||||
* and retains the settings from there on subsequent reboots ignoring the
|
||||
@@ -26,6 +26,8 @@ struct _WpSettingsPlugin
|
||||
{
|
||||
WpPlugin parent;
|
||||
|
||||
gchar *metadata_name;
|
||||
|
||||
WpImplMetadata *impl_metadata;
|
||||
|
||||
WpProperties *settings;
|
||||
@@ -37,6 +39,12 @@ struct _WpSettingsPlugin
|
||||
gboolean use_persistent_storage;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_METADATA_NAME,
|
||||
PROP_PROPERTIES,
|
||||
};
|
||||
|
||||
G_DECLARE_FINAL_TYPE (WpSettingsPlugin, wp_settings_plugin,
|
||||
WP, SETTINGS_PLUGIN, WpPlugin)
|
||||
G_DEFINE_TYPE (WpSettingsPlugin, wp_settings_plugin, WP_TYPE_PLUGIN)
|
||||
@@ -198,8 +206,8 @@ on_metadata_activated (WpMetadata * m, GAsyncResult * res, gpointer user_data)
|
||||
|
||||
if (!wp_object_activate_finish (WP_OBJECT (m), res, &error)) {
|
||||
g_clear_object (&self->impl_metadata);
|
||||
g_prefix_error (&error, "Failed to activate \"sm-settings\": \
|
||||
Metadata object ");
|
||||
g_prefix_error (&error, "Failed to activate \"%s\": "
|
||||
"Metadata object ", self->metadata_name);
|
||||
wp_transition_return_error (transition, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
@@ -268,8 +276,8 @@ on_metadata_activated (WpMetadata * m, GAsyncResult * res, gpointer user_data)
|
||||
wp_debug_object (self, "%s(%lu) = %s", setting, strlen(value), value);
|
||||
wp_metadata_set (m, 0, setting, "Spa:String:JSON", value);
|
||||
}
|
||||
wp_info_object (self, "loaded settings(%d) to \"sm-settings\" metadata",
|
||||
wp_properties_get_count (self->settings));
|
||||
wp_info_object (self, "loaded settings(%d) to \"%s\" metadata",
|
||||
wp_properties_get_count (self->settings), self->metadata_name);
|
||||
|
||||
|
||||
/* monitor changes in metadata. */
|
||||
@@ -287,7 +295,8 @@ wp_settings_plugin_enable (WpPlugin * plugin, WpTransition * transition)
|
||||
self->use_persistent_storage = false;
|
||||
|
||||
/* create metadata object */
|
||||
self->impl_metadata = wp_impl_metadata_new_full (core, "sm-settings", NULL);
|
||||
self->impl_metadata = wp_impl_metadata_new_full (core, self->metadata_name,
|
||||
NULL);
|
||||
wp_object_activate (WP_OBJECT (self->impl_metadata),
|
||||
WP_OBJECT_FEATURES_ALL,
|
||||
NULL,
|
||||
@@ -308,23 +317,73 @@ wp_settings_plugin_disable (WpPlugin * plugin)
|
||||
g_clear_object (&self->impl_metadata);
|
||||
|
||||
g_clear_object (&self->state);
|
||||
g_free (self->metadata_name);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_settings_plugin_set_property (GObject * object, guint property_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpSettingsPlugin *self = WP_SETTINGS_PLUGIN (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_METADATA_NAME:
|
||||
self->metadata_name = g_strdup (g_value_get_string (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_settings_plugin_get_property (GObject * object, guint property_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpSettingsPlugin *self = WP_SETTINGS_PLUGIN (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_METADATA_NAME:
|
||||
g_value_set_string (value, self->metadata_name);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_settings_plugin_class_init (WpSettingsPluginClass * klass)
|
||||
{
|
||||
WpPluginClass *plugin_class = (WpPluginClass *) klass;
|
||||
GObjectClass *object_class = (GObjectClass *) klass;
|
||||
|
||||
plugin_class->enable = wp_settings_plugin_enable;
|
||||
plugin_class->disable = wp_settings_plugin_disable;
|
||||
|
||||
object_class->set_property = wp_settings_plugin_set_property;
|
||||
object_class->get_property = wp_settings_plugin_get_property;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_METADATA_NAME,
|
||||
g_param_spec_string ("metadata-name", "metadata-name",
|
||||
"The metadata object to look after", NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
}
|
||||
|
||||
WP_PLUGIN_EXPORT gboolean
|
||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||
{
|
||||
const gchar *metadata_name = "sm-settings";
|
||||
|
||||
if (args) {
|
||||
metadata_name = g_variant_get_string(args, NULL);
|
||||
}
|
||||
|
||||
wp_plugin_register (g_object_new (wp_settings_plugin_get_type (),
|
||||
"name", "settings",
|
||||
"core", core,
|
||||
"metadata-name", metadata_name,
|
||||
NULL));
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -186,7 +186,7 @@ do_load_components(void *data, const char *location, const char *section,
|
||||
static void
|
||||
on_settings_ready (WpSettings *s, GAsyncResult *res, gpointer data)
|
||||
{
|
||||
WpCore *self = WP_CORE (data);
|
||||
WpInitTransition *self = WP_INIT_TRANSITION (data);
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
wp_info_object(self, "wpsettings object ready");
|
||||
@@ -206,7 +206,7 @@ on_settings_plugin_ready (WpPlugin *s, GAsyncResult *res, gpointer data)
|
||||
WpTransition *transition = WP_TRANSITION (data);
|
||||
WpCore *core = wp_transition_get_source_object (transition);
|
||||
g_autoptr (GError) error = NULL;
|
||||
g_autoptr (WpSettings) settings = wp_settings_get_instance (core);
|
||||
g_autoptr (WpSettings) settings = wp_settings_get_instance (core, NULL);
|
||||
|
||||
wp_info_object (self, "wpsettingsplugin object ready");
|
||||
|
||||
@@ -217,7 +217,7 @@ on_settings_plugin_ready (WpPlugin *s, GAsyncResult *res, gpointer data)
|
||||
}
|
||||
|
||||
wp_object_activate (WP_OBJECT (settings), WP_OBJECT_FEATURES_ALL, NULL,
|
||||
(GAsyncReadyCallback) on_settings_ready, g_object_ref (self));
|
||||
(GAsyncReadyCallback) on_settings_ready, self);
|
||||
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
|
||||
wp_info_object (self, "Activating wpsettings plugin");
|
||||
|
||||
wp_object_activate (WP_OBJECT (p), WP_OBJECT_FEATURES_ALL, NULL,
|
||||
(GAsyncReadyCallback) on_settings_plugin_ready, g_object_ref (self));
|
||||
(GAsyncReadyCallback) on_settings_plugin_ready, self);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@@ -32,6 +32,11 @@ typedef struct {
|
||||
(second client to our internal server) */
|
||||
WpCore *client_core;
|
||||
|
||||
/* Custom JSON config file if any,
|
||||
* this overrides the default conf file that is picked
|
||||
*/
|
||||
gchar *conf_file;
|
||||
|
||||
} WpBaseTestFixture;
|
||||
|
||||
static gboolean
|
||||
@@ -74,7 +79,13 @@ wp_base_test_fixture_setup (WpBaseTestFixture * self, WpBaseTestFlags flags)
|
||||
|
||||
/* init our core */
|
||||
props = wp_properties_new (PW_KEY_REMOTE_NAME, self->server.name, NULL);
|
||||
|
||||
if (self->conf_file)
|
||||
wp_properties_set (props, PW_KEY_CONFIG_NAME, self->conf_file);
|
||||
|
||||
self->core = wp_core_new (self->context, wp_properties_ref (props));
|
||||
g_assert_true (self->core);
|
||||
|
||||
g_signal_connect (self->core, "disconnected",
|
||||
(GCallback) disconnected_callback, self);
|
||||
|
||||
|
@@ -100,6 +100,13 @@ if get_option('dbus-tests')
|
||||
)
|
||||
endif
|
||||
|
||||
test(
|
||||
'test-settings',
|
||||
executable('test-settings', 'settings.c',
|
||||
dependencies: common_deps, c_args: common_args),
|
||||
env: common_env,
|
||||
)
|
||||
|
||||
test(
|
||||
'test-transition',
|
||||
executable('test-transition', 'transition.c',
|
||||
|
297
tests/wp/settings.c
Normal file
297
tests/wp/settings.c
Normal file
@@ -0,0 +1,297 @@
|
||||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2022 Collabora Ltd.
|
||||
* @author Ashok Sidipotu <ashok.sidipotu@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "../common/base-test-fixture.h"
|
||||
|
||||
/*
|
||||
* tests the loading & parsing of JSON conf file(pls check the settings.conf),
|
||||
* metadata updates, wpsetttings object creation and its API.
|
||||
*/
|
||||
typedef struct {
|
||||
WpBaseTestFixture base;
|
||||
|
||||
WpProperties *settings;
|
||||
|
||||
WpImplMetadata *impl_metadata;
|
||||
WpMetadata *metadata;
|
||||
|
||||
WpSettings *s;
|
||||
} TestSettingsFixture;
|
||||
|
||||
static void
|
||||
test_conf_file_setup (TestSettingsFixture *self, gconstpointer user_data)
|
||||
{
|
||||
self->base.conf_file =
|
||||
g_strdup_printf ("%s/settings.conf", g_getenv ("G_TEST_SRCDIR"));
|
||||
|
||||
wp_base_test_fixture_setup (&self->base, WP_BASE_TEST_FLAG_CLIENT_CORE);
|
||||
}
|
||||
|
||||
static void
|
||||
test_conf_file_teardown (TestSettingsFixture *self, gconstpointer user_data)
|
||||
{
|
||||
g_free (self->base.conf_file);
|
||||
wp_base_test_fixture_teardown (&self->base);
|
||||
}
|
||||
|
||||
static int
|
||||
dummy(void *data, const char *location, const char *section,
|
||||
const char *str, size_t len)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
test_conf_file (TestSettingsFixture *self, gconstpointer data)
|
||||
{
|
||||
struct pw_context *pw_ctx = wp_core_get_pw_context (self->base.core);
|
||||
|
||||
/* test if the "settings" section is present in the JSON config file */
|
||||
g_assert_true (pw_context_conf_section_for_each(pw_ctx,
|
||||
"wireplumber.settings", dummy, NULL));
|
||||
}
|
||||
|
||||
struct data {
|
||||
int count;
|
||||
WpProperties *settings;
|
||||
};
|
||||
|
||||
static int
|
||||
do_parse_settings (void *data, const char *location,
|
||||
const char *section, const char *str, size_t len)
|
||||
{
|
||||
struct data *d = data;
|
||||
g_autoptr (WpSpaJson) json = wp_spa_json_new_from_stringn (str, len);
|
||||
g_autoptr (WpIterator) iter = wp_spa_json_new_iterator (json);
|
||||
g_auto (GValue) item = G_VALUE_INIT;
|
||||
|
||||
if (!wp_spa_json_is_object (json)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (wp_iterator_next (iter, &item)) {
|
||||
WpSpaJson *j = g_value_get_boxed (&item);
|
||||
g_autofree gchar *name = wp_spa_json_parse_string (j);
|
||||
g_autofree gchar *value = NULL;
|
||||
|
||||
g_value_unset (&item);
|
||||
wp_iterator_next (iter, &item);
|
||||
j = g_value_get_boxed (&item);
|
||||
|
||||
value = wp_spa_json_parse_string (j);
|
||||
g_value_unset (&item);
|
||||
|
||||
if (name && value) {
|
||||
wp_properties_set (d->settings, name, value);
|
||||
d->count++;
|
||||
}
|
||||
}
|
||||
|
||||
g_debug ("parsed %d settings & rules from conf file\n", d->count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_parsing_setup (TestSettingsFixture *self, gconstpointer user_data)
|
||||
{
|
||||
test_conf_file_setup (self, user_data);
|
||||
|
||||
{
|
||||
struct pw_context *pw_ctx = wp_core_get_pw_context (self->base.core);
|
||||
g_autoptr (WpProperties) settings = wp_properties_new_empty();
|
||||
struct data data = { .settings = settings };
|
||||
|
||||
g_assert_false (pw_context_conf_section_for_each(pw_ctx,
|
||||
"wireplumber.settings", do_parse_settings, &data));
|
||||
|
||||
self->settings = g_steal_pointer (&settings);
|
||||
|
||||
/* total no.of properties in the conf file */
|
||||
g_assert_cmpint (data.count, ==, 3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
test_parsing_teardown (TestSettingsFixture *self, gconstpointer user_data)
|
||||
{
|
||||
g_clear_pointer (&self->settings, wp_properties_unref);
|
||||
|
||||
test_conf_file_teardown (self, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
test_parsing (TestSettingsFixture *self, gconstpointer data)
|
||||
{
|
||||
/* total no.of properties in the conf file */
|
||||
g_assert_cmpint (wp_properties_get_count(self->settings), ==, 3);
|
||||
}
|
||||
|
||||
static void
|
||||
on_metadata_activated (WpMetadata * m, GAsyncResult * res, gpointer user_data)
|
||||
{
|
||||
TestSettingsFixture *self = user_data;
|
||||
g_autoptr (GError) error = NULL;
|
||||
g_autoptr (WpIterator) it = NULL;
|
||||
g_auto (GValue) item = G_VALUE_INIT;
|
||||
|
||||
g_assert_true(wp_object_activate_finish (WP_OBJECT (m), res, NULL));
|
||||
|
||||
for (it = wp_properties_new_iterator (self->settings);
|
||||
wp_iterator_next (it, &item);
|
||||
g_value_unset (&item)) {
|
||||
WpPropertiesItem *pi = g_value_get_boxed (&item);
|
||||
|
||||
const gchar *setting = wp_properties_item_get_key (pi);
|
||||
const gchar *value = wp_properties_item_get_value (pi);
|
||||
|
||||
wp_metadata_set (m, 0, setting, "Spa:String:JSON", value);
|
||||
}
|
||||
g_debug ("loaded settings(%d) to \"test-settings\" metadata\n",
|
||||
wp_properties_get_count (self->settings));
|
||||
|
||||
self->metadata = g_object_ref(m);
|
||||
g_main_loop_quit(self->base.loop);
|
||||
}
|
||||
|
||||
static void
|
||||
test_metadata_setup (TestSettingsFixture *self, gconstpointer user_data)
|
||||
{
|
||||
test_parsing_setup (self, user_data);
|
||||
|
||||
{
|
||||
self->impl_metadata = wp_impl_metadata_new_full (self->base.core,
|
||||
"test-settings", NULL);
|
||||
|
||||
wp_object_activate (WP_OBJECT (self->impl_metadata),
|
||||
WP_OBJECT_FEATURES_ALL,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)on_metadata_activated,
|
||||
self);
|
||||
|
||||
g_main_loop_run (self->base.loop);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
test_metadata_teardown (TestSettingsFixture *self, gconstpointer user_data)
|
||||
{
|
||||
test_parsing_teardown (self, user_data);
|
||||
|
||||
g_clear_object (&self->impl_metadata);
|
||||
g_clear_object (&self->metadata);
|
||||
}
|
||||
|
||||
static void
|
||||
test_metadata (TestSettingsFixture *self, gconstpointer data)
|
||||
{
|
||||
g_autoptr (WpProperties) settings = wp_properties_new_empty();
|
||||
|
||||
g_autoptr (WpIterator) it = wp_metadata_new_iterator
|
||||
(WP_METADATA (self->metadata), 0);
|
||||
g_auto (GValue) val = G_VALUE_INIT;
|
||||
|
||||
for (; wp_iterator_next (it, &val); g_value_unset (&val)) {
|
||||
const gchar *setting, *value;
|
||||
wp_metadata_iterator_item_extract (&val, NULL, &setting, NULL, &value);
|
||||
wp_properties_set (settings, setting, value);
|
||||
g_debug ("%s(%lu) = %s\n", setting, strlen(value), value);
|
||||
}
|
||||
|
||||
/* match the settings loaded from conf file and metadata */
|
||||
g_assert_true (wp_properties_matches (self->settings, settings));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
on_settings_ready (WpSettings *s, GAsyncResult *res, gpointer data)
|
||||
{
|
||||
TestSettingsFixture *self = data;
|
||||
|
||||
g_assert_true(wp_object_activate_finish (WP_OBJECT (s), res, NULL));
|
||||
|
||||
g_main_loop_quit(self->base.loop);
|
||||
}
|
||||
|
||||
static void
|
||||
test_wpsettings_setup (TestSettingsFixture *self, gconstpointer user_data)
|
||||
{
|
||||
test_metadata_setup (self, user_data);
|
||||
|
||||
{
|
||||
self->s = wp_settings_get_instance (self->base.core, "test-settings");
|
||||
|
||||
wp_object_activate (WP_OBJECT (self->s),
|
||||
WP_OBJECT_FEATURES_ALL,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)on_settings_ready,
|
||||
self);
|
||||
g_main_loop_run (self->base.loop);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
test_wpsettings_teardown (TestSettingsFixture *self, gconstpointer user_data)
|
||||
{
|
||||
test_metadata_teardown (self, user_data);
|
||||
g_clear_object (&self->s);
|
||||
}
|
||||
|
||||
static void
|
||||
test_wpsettings (TestSettingsFixture *self, gconstpointer data)
|
||||
{
|
||||
WpSettings *s = self->s;
|
||||
g_assert_false (wp_settings_get_boolean (s, "property1"));
|
||||
g_assert_true (wp_settings_get_boolean (s, "property2"));
|
||||
|
||||
/* test the wp_settings_get_instance() API */
|
||||
{
|
||||
g_autoptr (WpSettings) s1 =
|
||||
wp_settings_get_instance (self->base.core, "test-settings");
|
||||
g_autoptr (WpSettings) s2 =
|
||||
wp_settings_get_instance (self->base.core, "test-settings");
|
||||
g_autoptr (WpSettings) s3 =
|
||||
wp_settings_get_instance (self->base.core, "blah-blah");
|
||||
|
||||
g_assert_true (s == s1);
|
||||
g_assert_true (s1 == s2);
|
||||
g_assert_false (s1 == s3);
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
g_autoptr (WpSettings) s4 =
|
||||
wp_settings_get_instance (self->base.core, NULL);
|
||||
|
||||
g_auto (GValue) value = G_VALUE_INIT;
|
||||
g_object_get_property (G_OBJECT(s4), "metadata-name", &value);
|
||||
|
||||
g_assert_cmpstr (g_value_get_string (&value), ==, "sm-settings");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc, gchar *argv[])
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
wp_init (WP_INIT_ALL);
|
||||
|
||||
g_test_add ("/wp/settings/conf-file-loading", TestSettingsFixture, NULL,
|
||||
test_conf_file_setup, test_conf_file, test_conf_file_teardown);
|
||||
g_test_add ("/wp/settings/parsing", TestSettingsFixture, NULL,
|
||||
test_parsing_setup, test_parsing, test_parsing_teardown);
|
||||
g_test_add ("/wp/settings/metadata-creation", TestSettingsFixture, NULL,
|
||||
test_metadata_setup, test_metadata, test_metadata_teardown);
|
||||
g_test_add ("/wp/settings/wpsettings-creation", TestSettingsFixture, NULL,
|
||||
test_wpsettings_setup, test_wpsettings, test_wpsettings_teardown);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
111
tests/wp/settings.conf
Normal file
111
tests/wp/settings.conf
Normal file
@@ -0,0 +1,111 @@
|
||||
# Client config file for PipeWire version "0.3.48" #
|
||||
#
|
||||
# Copy and edit this file in /usr/local/etc/pipewire for system-wide changes
|
||||
# or in ~/.config/pipewire for local changes.
|
||||
#
|
||||
# It is also possible to place a file with an updated section in
|
||||
# /usr/local/etc/pipewire/client.conf.d/ for system-wide changes or in
|
||||
# ~/.config/pipewire/client.conf.d/ for local changes.
|
||||
#
|
||||
context.properties = {
|
||||
## Configure properties in the system.
|
||||
#mem.warn-mlock = false
|
||||
#mem.allow-mlock = true
|
||||
#mem.mlock-all = false
|
||||
log.level = 0
|
||||
|
||||
#default.clock.quantum-limit = 8192
|
||||
}
|
||||
|
||||
context.spa-libs = {
|
||||
#<factory-name regex> = <library-name>
|
||||
#
|
||||
# Used to find spa factory names. It maps an spa factory name
|
||||
# regular expression to a library name that should contain
|
||||
# that factory.
|
||||
#
|
||||
audio.convert.* = audioconvert/libspa-audioconvert
|
||||
support.* = support/libspa-support
|
||||
}
|
||||
|
||||
context.modules = [
|
||||
#{ name = <module-name>
|
||||
# [ args = { <key> = <value> ... } ]
|
||||
# [ flags = [ [ ifexists ] [ nofail ] ]
|
||||
#}
|
||||
#
|
||||
# Loads a module with the given parameters.
|
||||
# If ifexists is given, the module is ignored when it is not found.
|
||||
# If nofail is given, module initialization failures are ignored.
|
||||
#
|
||||
|
||||
# The native communication protocol.
|
||||
{ name = libpipewire-module-protocol-native }
|
||||
|
||||
# Allows creating nodes that run in the context of the
|
||||
# client. Is used by all clients that want to provide
|
||||
# data to PipeWire.
|
||||
{ name = libpipewire-module-client-node }
|
||||
|
||||
# Allows creating devices that run in the context of the
|
||||
# client. Is used by the session manager.
|
||||
{ name = libpipewire-module-client-device }
|
||||
|
||||
# Makes a factory for wrapping nodes in an adapter with a
|
||||
# converter and resampler.
|
||||
{ name = libpipewire-module-adapter }
|
||||
|
||||
# Allows applications to create metadata objects. It creates
|
||||
# a factory for Metadata objects.
|
||||
{ name = libpipewire-module-metadata }
|
||||
|
||||
# Provides factories to make session manager objects.
|
||||
{ name = libpipewire-module-session-manager }
|
||||
]
|
||||
|
||||
wireplumber.settings = {
|
||||
property1 = false
|
||||
property2 = true
|
||||
rule1 = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
pipewire.access = "flatpak"
|
||||
media.category = "Manager"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
default_permissions = "all",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
pipewire.access = "flatpak"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
default_permissions = "rx",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
pipewire.access = "restricted"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
quirks = {
|
||||
default_permissions = "rx",
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
}
|
@@ -49,3 +49,9 @@ test(
|
||||
args: ['async-activation.lua'],
|
||||
env: common_env,
|
||||
)
|
||||
test(
|
||||
'test-lua-settings',
|
||||
script_tester,
|
||||
args: ['settings.lua'],
|
||||
env: common_env,
|
||||
)
|
||||
|
@@ -12,9 +12,14 @@ typedef struct {
|
||||
WpBaseTestFixture base;
|
||||
} ScriptRunnerFixture;
|
||||
|
||||
#define METADATA_NAME "test-settings"
|
||||
|
||||
static void
|
||||
script_runner_setup (ScriptRunnerFixture *f, gconstpointer data)
|
||||
{
|
||||
f->base.conf_file =
|
||||
g_strdup_printf ("%s/settings.conf", g_getenv ("G_TEST_SRCDIR"));
|
||||
|
||||
wp_base_test_fixture_setup (&f->base, 0);
|
||||
}
|
||||
|
||||
@@ -44,6 +49,25 @@ script_run (ScriptRunnerFixture *f, gconstpointer data)
|
||||
g_main_loop_run (f->base.loop);
|
||||
g_clear_object (&plugin);
|
||||
|
||||
{
|
||||
g_autoptr (WpSettings) settings = NULL;
|
||||
|
||||
wp_core_load_component (f->base.core,
|
||||
"libwireplumber-module-settings", "module",
|
||||
g_variant_new_string (METADATA_NAME), &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
plugin = wp_plugin_find (f->base.core, "settings");
|
||||
wp_object_activate (WP_OBJECT (plugin), WP_PLUGIN_FEATURE_ENABLED,
|
||||
NULL, (GAsyncReadyCallback) test_object_activate_finish_cb, f);
|
||||
g_main_loop_run (f->base.loop);
|
||||
|
||||
settings = wp_settings_get_instance (f->base.core, METADATA_NAME);
|
||||
|
||||
wp_object_activate (WP_OBJECT (settings), WP_PLUGIN_FEATURE_ENABLED,
|
||||
NULL, (GAsyncReadyCallback) test_object_activate_finish_cb, f);
|
||||
g_main_loop_run (f->base.loop);
|
||||
}
|
||||
wp_core_load_component (f->base.core, (const gchar *) data, "script/lua",
|
||||
NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
8
tests/wplua/scripts/settings.lua
Normal file
8
tests/wplua/scripts/settings.lua
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
-- tests the lua API of WpSettings, this file tests the settings present in
|
||||
-- settings.conf
|
||||
|
||||
assert (Settings.get_boolean("property1", "test-settings") == false)
|
||||
assert (Settings.get_boolean("property2", "test-settings") == true)
|
||||
|
||||
assert (Settings.get_boolean("property1") == false)
|
130
tests/wplua/settings.conf
Normal file
130
tests/wplua/settings.conf
Normal file
@@ -0,0 +1,130 @@
|
||||
# Client config file for PipeWire version "0.3.48" #
|
||||
#
|
||||
# Copy and edit this file in /usr/local/etc/pipewire for system-wide changes
|
||||
# or in ~/.config/pipewire for local changes.
|
||||
#
|
||||
# It is also possible to place a file with an updated section in
|
||||
# /usr/local/etc/pipewire/client.conf.d/ for system-wide changes or in
|
||||
# ~/.config/pipewire/client.conf.d/ for local changes.
|
||||
#
|
||||
context.properties = {
|
||||
## Configure properties in the system.
|
||||
#mem.warn-mlock = false
|
||||
#mem.allow-mlock = true
|
||||
#mem.mlock-all = false
|
||||
log.level = 0
|
||||
|
||||
#default.clock.quantum-limit = 8192
|
||||
}
|
||||
|
||||
context.spa-libs = {
|
||||
#<factory-name regex> = <library-name>
|
||||
#
|
||||
# Used to find spa factory names. It maps an spa factory name
|
||||
# regular expression to a library name that should contain
|
||||
# that factory.
|
||||
#
|
||||
audio.convert.* = audioconvert/libspa-audioconvert
|
||||
support.* = support/libspa-support
|
||||
}
|
||||
|
||||
context.modules = [
|
||||
#{ name = <module-name>
|
||||
# [ args = { <key> = <value> ... } ]
|
||||
# [ flags = [ [ ifexists ] [ nofail ] ]
|
||||
#}
|
||||
#
|
||||
# Loads a module with the given parameters.
|
||||
# If ifexists is given, the module is ignored when it is not found.
|
||||
# If nofail is given, module initialization failures are ignored.
|
||||
#
|
||||
|
||||
# The native communication protocol.
|
||||
{ name = libpipewire-module-protocol-native }
|
||||
|
||||
# Allows creating nodes that run in the context of the
|
||||
# client. Is used by all clients that want to provide
|
||||
# data to PipeWire.
|
||||
{ name = libpipewire-module-client-node }
|
||||
|
||||
# Allows creating devices that run in the context of the
|
||||
# client. Is used by the session manager.
|
||||
{ name = libpipewire-module-client-device }
|
||||
|
||||
# Makes a factory for wrapping nodes in an adapter with a
|
||||
# converter and resampler.
|
||||
{ name = libpipewire-module-adapter }
|
||||
|
||||
# Allows applications to create metadata objects. It creates
|
||||
# a factory for Metadata objects.
|
||||
{ name = libpipewire-module-metadata }
|
||||
|
||||
# Provides factories to make session manager objects.
|
||||
{ name = libpipewire-module-session-manager }
|
||||
]
|
||||
|
||||
filter.properties = {
|
||||
#node.latency = 1024/48000
|
||||
}
|
||||
|
||||
stream.properties = {
|
||||
#node.latency = 1024/48000
|
||||
#node.autoconnect = true
|
||||
#resample.quality = 4
|
||||
#channelmix.normalize = false
|
||||
#channelmix.mix-lfe = false
|
||||
#channelmix.upmix = true
|
||||
#channelmix.upmix-method = psd # none, simple
|
||||
#channelmix.lfe-cutoff = 120
|
||||
#channelmix.fc-cutoff = 6000
|
||||
#channelmix.rear-delay = 12.0
|
||||
#channelmix.stereo-widen = 0.1
|
||||
#channelmix.hilbert-taps = 0
|
||||
}
|
||||
|
||||
wireplumber.settings = {
|
||||
property1 = false
|
||||
property2 = true
|
||||
rule1 = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
pipewire.access = "flatpak"
|
||||
media.category = "Manager"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
default_permissions = "all",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
pipewire.access = "flatpak"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
update-props = {
|
||||
default_permissions = "rx",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
pipewire.access = "restricted"
|
||||
}
|
||||
]
|
||||
actions = {
|
||||
quirks = {
|
||||
default_permissions = "rx",
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
}
|
Reference in New Issue
Block a user