Files
wireplumber/tests/wp/json-utils.c
George Kiagiadakis 89ac416e99 lib: add new json-utils set of functions
The purpose is to wrap some utilities that pipewire provides that use JSON.

Start by wrapping pw_conf_match_rules(), which despite its name, it has nothing
to do with the configuration object. It operates directly on JSON and can be
useful to work with match rules outside the context of configuration files.
2023-11-07 16:36:49 +02:00

348 lines
11 KiB
C

/* WirePlumber
*
* Copyright © 2023 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include "../common/test-log.h"
static void
test_match_rules_update_properties (void)
{
static const gchar * const rules_json_string =
"["
" {"
" matches = ["
" {"
" device.name = \"~alsa_card.*\""
" }"
" ]"
" actions = {"
" update-props = {"
" api.alsa.use-acp = true"
" api.acp.auto-port = false"
" }"
" }"
" }"
" {"
" matches = ["
" {"
" node.name = \"alsa_output.0.my-alsa-device\""
" }"
" ]"
" actions = {"
" update-props = {"
" audio.rate = 96000"
" node.description = \"My ALSA Node\""
" media.class = null"
" }"
" }"
" }"
"]";
g_autoptr (WpSpaJson) rules = wp_spa_json_new_from_stringn (rules_json_string,
strlen (rules_json_string));
g_assert_nonnull (rules);
/* Unmatched */
{
g_autoptr (WpProperties) match_props = NULL;
match_props = wp_properties_new (
"device.name", "unmatched-device-name",
NULL);
g_assert_cmpint (wp_json_utils_match_rules_update_properties (rules, match_props), ==, 0);
}
/* Match regex with props filled */
{
g_autoptr (WpProperties) match_props = NULL;
const gchar *str = NULL;
match_props = wp_properties_new (
"device.name", "alsa_card_0.my-alsa-device",
NULL);
g_assert_nonnull (match_props);
str = wp_properties_get (match_props, "device.name");
g_assert_cmpstr (str, ==, "alsa_card_0.my-alsa-device");
str = wp_properties_get (match_props, "api.alsa.use-acp");
g_assert_null (str);
str = wp_properties_get (match_props, "api.acp.auto-port");
g_assert_null (str);
g_assert_cmpint (wp_json_utils_match_rules_update_properties (rules, match_props), ==, 2);
str = wp_properties_get (match_props, "device.name");
g_assert_cmpstr (str, ==, "alsa_card_0.my-alsa-device");
str = wp_properties_get (match_props, "api.alsa.use-acp");
g_assert_cmpstr (str, ==, "true");
str = wp_properties_get (match_props, "api.acp.auto-port");
g_assert_cmpstr (str, ==, "false");
}
/* Match equal with props filled */
{
g_autoptr (WpProperties) match_props = NULL;
const gchar *str = NULL;
match_props = wp_properties_new (
"node.name", "alsa_output.0.my-alsa-device",
NULL);
g_assert_nonnull (match_props);
str = wp_properties_get (match_props, "node.name");
g_assert_cmpstr (str, ==, "alsa_output.0.my-alsa-device");
str = wp_properties_get (match_props, "audio.rate");
g_assert_null (str);
str = wp_properties_get (match_props, "node.description");
g_assert_null (str);
str = wp_properties_get (match_props, "media.class");
g_assert_null (str);
g_assert_cmpint (wp_json_utils_match_rules_update_properties (rules, match_props), ==, 2);
str = wp_properties_get (match_props, "node.name");
g_assert_cmpstr (str, ==, "alsa_output.0.my-alsa-device");
str = wp_properties_get (match_props, "audio.rate");
g_assert_cmpstr (str, ==, "96000");
str = wp_properties_get (match_props, "node.description");
g_assert_cmpstr (str, ==, "My ALSA Node");
str = wp_properties_get (match_props, "media.class");
g_assert_null (str);
}
/* Match equal with 1 prop updated */
{
g_autoptr (WpProperties) match_props = NULL;
const gchar *str = NULL;
match_props = wp_properties_new (
"node.name", "alsa_output.0.my-alsa-device",
"audio.rate", "96000",
"node.description", "Test",
NULL);
g_assert_nonnull (match_props);
str = wp_properties_get (match_props, "node.name");
g_assert_cmpstr (str, ==, "alsa_output.0.my-alsa-device");
str = wp_properties_get (match_props, "audio.rate");
g_assert_cmpstr (str, ==, "96000");
str = wp_properties_get (match_props, "node.description");
g_assert_cmpstr (str, ==, "Test");
str = wp_properties_get (match_props, "media.class");
g_assert_null (str);
g_assert_cmpint (wp_json_utils_match_rules_update_properties (rules, match_props), ==, 1);
str = wp_properties_get (match_props, "node.name");
g_assert_cmpstr (str, ==, "alsa_output.0.my-alsa-device");
str = wp_properties_get (match_props, "audio.rate");
g_assert_cmpstr (str, ==, "96000");
str = wp_properties_get (match_props, "node.description");
g_assert_cmpstr (str, ==, "My ALSA Node");
str = wp_properties_get (match_props, "media.class");
g_assert_null (str);
}
/* Match equal with prop deleted */
{
g_autoptr (WpProperties) match_props = NULL;
const gchar *str = NULL;
match_props = wp_properties_new (
"node.name", "alsa_output.0.my-alsa-device",
"media.class", "Audio/Sink",
"audio.rate", "48000",
"node.description", "Test",
NULL);
g_assert_nonnull (match_props);
str = wp_properties_get (match_props, "node.name");
g_assert_cmpstr (str, ==, "alsa_output.0.my-alsa-device");
str = wp_properties_get (match_props, "audio.rate");
g_assert_cmpstr (str, ==, "48000");
str = wp_properties_get (match_props, "node.description");
g_assert_cmpstr (str, ==, "Test");
str = wp_properties_get (match_props, "media.class");
g_assert_cmpstr (str, ==, "Audio/Sink");
g_assert_cmpint (wp_json_utils_match_rules_update_properties (rules, match_props), ==, 3);
str = wp_properties_get (match_props, "node.name");
g_assert_cmpstr (str, ==, "alsa_output.0.my-alsa-device");
str = wp_properties_get (match_props, "audio.rate");
g_assert_cmpstr (str, ==, "96000");
str = wp_properties_get (match_props, "node.description");
g_assert_cmpstr (str, ==, "My ALSA Node");
str = wp_properties_get (match_props, "media.class");
g_assert_null (str);
}
}
static gboolean
match_rules_cb (gpointer data, const gchar * action, WpSpaJson * value,
GError ** error)
{
WpProperties *match_props = data;
if (g_str_equal (action, "update-props")) {
wp_properties_update_from_json (match_props, value);
}
else if (g_str_equal (action, "set-answer")) {
g_autofree gchar *str = wp_spa_json_to_string (value);
wp_properties_set (match_props, "answer.universe", str);
}
else if (g_str_equal (action, "generate-error")) {
g_autofree gchar *str = wp_spa_json_parse_string (value);
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
"error: %s", str);
return FALSE;
}
else if (g_str_equal (action, "set-description")) {
g_autofree gchar *str = wp_spa_json_parse_string (value);
wp_properties_set (match_props, "device.description", str);
}
return TRUE;
}
static void
test_match_rules (void)
{
static const gchar * const rules_json_string =
"["
" {"
" matches = ["
" {"
" device.name = \"~alsa_card.*\""
" }"
" ]"
" actions = {"
" update-props = {"
" device.name = alsa_card.1"
" api.acp.auto-port = false"
" }"
" set-answer = 42"
" }"
" }"
" {"
" matches = ["
" {"
" test.error = true"
" }"
" ]"
" actions = {"
" generate-error = \"test.error is true\""
" }"
" }"
" {"
" matches = ["
" {"
" device.name = \"alsa_card.1\""
" }"
" ]"
" actions = {"
" set-description = \"My ALSA Device\""
" }"
" }"
"]";
g_autoptr (WpSpaJson) rules = wp_spa_json_new_from_stringn (rules_json_string,
strlen (rules_json_string));
g_assert_nonnull (rules);
/* no error */
{
g_autoptr (GError) error = NULL;
g_autoptr (WpProperties) match_props = NULL;
const gchar *str = NULL;
match_props = wp_properties_new (
"device.name", "alsa_card.0",
"test.error", "false",
NULL);
str = wp_properties_get (match_props, "device.name");
g_assert_cmpstr (str, ==, "alsa_card.0");
str = wp_properties_get (match_props, "api.acp.auto-port");
g_assert_null (str);
str = wp_properties_get (match_props, "answer.universe");
g_assert_null (str);
str = wp_properties_get (match_props, "test.error");
g_assert_cmpstr (str, ==, "false");
str = wp_properties_get (match_props, "device.description");
g_assert_null (str);
g_assert_true (wp_json_utils_match_rules (rules, match_props, match_rules_cb,
match_props, &error));
g_assert_no_error (error);
str = wp_properties_get (match_props, "device.name");
g_assert_cmpstr (str, ==, "alsa_card.1");
str = wp_properties_get (match_props, "api.acp.auto-port");
g_assert_cmpstr (str, ==, "false");
str = wp_properties_get (match_props, "answer.universe");
g_assert_cmpstr (str, ==, "42");
str = wp_properties_get (match_props, "test.error");
g_assert_cmpstr (str, ==, "false");
str = wp_properties_get (match_props, "device.description");
g_assert_cmpstr (str, ==, "My ALSA Device");
}
/* with error */
{
g_autoptr (GError) error = NULL;
g_autoptr (WpProperties) match_props = NULL;
const gchar *str = NULL;
match_props = wp_properties_new (
"device.name", "alsa_card.256",
"test.error", "true",
NULL);
str = wp_properties_get (match_props, "device.name");
g_assert_cmpstr (str, ==, "alsa_card.256");
str = wp_properties_get (match_props, "api.acp.auto-port");
g_assert_null (str);
str = wp_properties_get (match_props, "answer.universe");
g_assert_null (str);
str = wp_properties_get (match_props, "test.error");
g_assert_cmpstr (str, ==, "true");
str = wp_properties_get (match_props, "device.description");
g_assert_null (str);
g_assert_false (wp_json_utils_match_rules (rules, match_props, match_rules_cb,
match_props, &error));
g_assert_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED);
g_assert_cmpstr (error->message, ==, "error: test.error is true");
str = wp_properties_get (match_props, "device.name");
g_assert_cmpstr (str, ==, "alsa_card.1");
str = wp_properties_get (match_props, "api.acp.auto-port");
g_assert_cmpstr (str, ==, "false");
str = wp_properties_get (match_props, "answer.universe");
g_assert_cmpstr (str, ==, "42");
str = wp_properties_get (match_props, "test.error");
g_assert_cmpstr (str, ==, "true");
str = wp_properties_get (match_props, "device.description");
g_assert_null (str);
}
}
gint
main (gint argc, gchar *argv[])
{
g_test_init (&argc, &argv, NULL);
g_log_set_writer_func (wp_log_writer_default, NULL, NULL);
g_test_add_func ("/wp/json-utils/match_rules_update_props",
test_match_rules_update_properties);
g_test_add_func ("/wp/json-utils/match_rules", test_match_rules);
return g_test_run ();
}