mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-21 04:08:18 +02:00
This API allows handling of collections easily. It mainly allows creating them, destroying them, collect globals into a them and dropping glovals from them. The manager also automatically destroys a collection of all globals where dropped from the collection.
446 lines
16 KiB
C
446 lines
16 KiB
C
/* WirePlumber
|
|
*
|
|
* Copyright © 2025 Collabora Ltd.
|
|
* @author Julian Bouzas <julian.bouzas@collabora.com>
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "../common/base-test-fixture.h"
|
|
|
|
#define COLLECTION_A_NAME "sm-collection-a"
|
|
#define COLLECTION_B_NAME "sm-collection-b"
|
|
#define COLLECTION_C_NAME "sm-collection-c"
|
|
#define COLLECTION_MANAGER_METADATA_NAME "sm-collection-manager"
|
|
|
|
typedef struct {
|
|
WpBaseTestFixture base;
|
|
WpImplMetadata *collection_a_metadata;
|
|
WpImplMetadata *collection_b_metadata;
|
|
WpImplMetadata *collection_manager_metadata;
|
|
WpCollectionManager *collection_manager;
|
|
WpCollection *collection_a;
|
|
WpCollection *collection_b;
|
|
} TestCollectionManagerFixture;
|
|
|
|
static void
|
|
on_metadata_activated (WpMetadata * m, GAsyncResult * res,
|
|
gpointer d)
|
|
{
|
|
TestCollectionManagerFixture *self = d;
|
|
g_assert_true (wp_object_activate_finish (WP_OBJECT (m), res, NULL));
|
|
g_main_loop_quit (self->base.loop);
|
|
}
|
|
|
|
static void
|
|
on_collection_manager_metadata_activated (WpMetadata * m, GAsyncResult * res,
|
|
gpointer d)
|
|
{
|
|
TestCollectionManagerFixture *self = d;
|
|
g_assert_true (wp_object_activate_finish (WP_OBJECT (m), res, NULL));
|
|
|
|
/* Add collections A and B */
|
|
wp_metadata_set (m, 0, COLLECTION_A_NAME, "Spa:String:JSON", "1");
|
|
wp_metadata_set (m, 0, COLLECTION_B_NAME, "Spa:String:JSON", "1");
|
|
|
|
g_main_loop_quit (self->base.loop);
|
|
}
|
|
|
|
static void
|
|
on_collection_manager_ready (WpCollectionManager *s, GAsyncResult *res,
|
|
gpointer d)
|
|
{
|
|
TestCollectionManagerFixture *self = d;
|
|
|
|
g_assert_true (wp_object_activate_finish (WP_OBJECT (s), res, NULL));
|
|
|
|
wp_core_register_object (self->base.core, g_object_ref (s));
|
|
|
|
g_main_loop_quit (self->base.loop);
|
|
}
|
|
|
|
static void
|
|
collection_manager_setup (TestCollectionManagerFixture *self, gconstpointer d)
|
|
{
|
|
wp_base_test_fixture_setup (&self->base, WP_BASE_TEST_FLAG_CLIENT_CORE);
|
|
|
|
/* Create collection A metadata and activate it */
|
|
self->collection_a_metadata = wp_impl_metadata_new_full (
|
|
self->base.core, COLLECTION_A_NAME,
|
|
wp_properties_new ("wireplumber.collection", "true", NULL));
|
|
wp_object_activate (WP_OBJECT (self->collection_a_metadata),
|
|
WP_OBJECT_FEATURES_ALL, NULL,
|
|
(GAsyncReadyCallback)on_metadata_activated, self);
|
|
g_main_loop_run (self->base.loop);
|
|
|
|
/* Create collection B metadata and activate it */
|
|
self->collection_b_metadata = wp_impl_metadata_new_full (
|
|
self->base.core, COLLECTION_B_NAME,
|
|
wp_properties_new ("wireplumber.collection", "true", NULL));
|
|
wp_object_activate (WP_OBJECT (self->collection_b_metadata),
|
|
WP_OBJECT_FEATURES_ALL, NULL,
|
|
(GAsyncReadyCallback)on_metadata_activated, self);
|
|
g_main_loop_run (self->base.loop);
|
|
|
|
/* Create collection manager metadata and activate it */
|
|
self->collection_manager_metadata = wp_impl_metadata_new_full (
|
|
self->base.core, COLLECTION_MANAGER_METADATA_NAME,
|
|
wp_properties_new ("wireplumber.collection-manager", "true", NULL));
|
|
wp_object_activate (WP_OBJECT (self->collection_manager_metadata),
|
|
WP_OBJECT_FEATURES_ALL, NULL,
|
|
(GAsyncReadyCallback)on_collection_manager_metadata_activated, self);
|
|
g_main_loop_run (self->base.loop);
|
|
|
|
/* Create the collection manager and activate it */
|
|
self->collection_manager = wp_collection_manager_new (self->base.core,
|
|
COLLECTION_MANAGER_METADATA_NAME);
|
|
wp_object_activate (WP_OBJECT (self->collection_manager),
|
|
WP_OBJECT_FEATURES_ALL,
|
|
NULL,
|
|
(GAsyncReadyCallback)on_collection_manager_ready,
|
|
self);
|
|
g_main_loop_run (self->base.loop);
|
|
|
|
/* Get collections A and B */
|
|
self->collection_a = wp_collection_manager_get_collection (
|
|
self->collection_manager, COLLECTION_A_NAME);
|
|
g_assert_nonnull (self->collection_a);
|
|
self->collection_b = wp_collection_manager_get_collection (
|
|
self->collection_manager, COLLECTION_B_NAME);
|
|
g_assert_nonnull (self->collection_b);
|
|
}
|
|
|
|
static void
|
|
collection_manager_teardown (TestCollectionManagerFixture *self,
|
|
gconstpointer d)
|
|
{
|
|
g_clear_object (&self->collection_b);
|
|
g_clear_object (&self->collection_a);
|
|
g_clear_object (&self->collection_manager);
|
|
g_clear_object (&self->collection_manager_metadata);
|
|
g_clear_object (&self->collection_b_metadata);
|
|
g_clear_object (&self->collection_a_metadata);
|
|
wp_base_test_fixture_teardown (&self->base);
|
|
}
|
|
|
|
static void
|
|
on_collection_created (WpCollectionManager * cm, GAsyncResult * res, gpointer d)
|
|
{
|
|
TestCollectionManagerFixture *self = d;
|
|
WpCollection *c = wp_collection_manager_create_collection_finish (cm, res,
|
|
NULL);
|
|
g_assert_nonnull (c);
|
|
g_assert_true (WP_IS_COLLECTION (c));
|
|
g_main_loop_quit (self->base.loop);
|
|
}
|
|
|
|
static void
|
|
test_collection_manager_collection (TestCollectionManagerFixture *self,
|
|
gconstpointer d)
|
|
{
|
|
g_autoptr (WpImplMetadata) collection_c_metadata;
|
|
|
|
/* Make sure the manager has 2 collections */
|
|
g_assert_cmpuint (wp_collection_manager_get_collection_count (
|
|
self->collection_manager), ==, 2);
|
|
|
|
/* Make sure collections A and B were added */
|
|
g_assert_true (wp_collection_manager_has_collection (self->collection_manager,
|
|
COLLECTION_A_NAME));
|
|
g_assert_true (wp_collection_manager_has_collection (self->collection_manager,
|
|
COLLECTION_B_NAME));
|
|
|
|
/* Make sure collection C was not added */
|
|
g_assert_false (wp_collection_manager_has_collection (self->collection_manager,
|
|
COLLECTION_C_NAME));
|
|
|
|
/* Create collection C metadata and activate it */
|
|
collection_c_metadata = wp_impl_metadata_new_full (
|
|
self->base.core, COLLECTION_C_NAME,
|
|
wp_properties_new ("wireplumber.collection", "true", NULL));
|
|
wp_object_activate (WP_OBJECT (collection_c_metadata),
|
|
WP_OBJECT_FEATURES_ALL, NULL,
|
|
(GAsyncReadyCallback)on_metadata_activated, self);
|
|
g_main_loop_run (self->base.loop);
|
|
|
|
/* Make sure collection C is still not added */
|
|
g_assert_false (wp_collection_manager_has_collection (self->collection_manager,
|
|
COLLECTION_C_NAME));
|
|
|
|
/* Create collection C */
|
|
wp_collection_manager_create_collection (self->collection_manager,
|
|
COLLECTION_C_NAME, NULL, (GAsyncReadyCallback)on_collection_created, self);
|
|
g_main_loop_run (self->base.loop);
|
|
|
|
/* Make sure the manager has 3 collections */
|
|
g_assert_cmpuint (wp_collection_manager_get_collection_count (
|
|
self->collection_manager), ==, 3);
|
|
|
|
/* Iterate collections */
|
|
{
|
|
g_autoptr (WpIterator) iter = NULL;
|
|
g_auto (GValue) val = G_VALUE_INIT;
|
|
gboolean has_collection_a = FALSE;
|
|
gboolean has_collection_b = FALSE;
|
|
gboolean has_collection_c = FALSE;
|
|
guint count = 0;
|
|
|
|
iter = wp_collection_manager_new_collection_iterator (
|
|
self->collection_manager);
|
|
g_assert_nonnull (iter);
|
|
|
|
while (wp_iterator_next (iter, &val)) {
|
|
WpCollection *c = g_value_get_object (&val);
|
|
g_assert_nonnull (c);
|
|
if (g_str_equal (wp_collection_get_name (c), COLLECTION_A_NAME))
|
|
has_collection_a = TRUE;
|
|
if (g_str_equal (wp_collection_get_name (c), COLLECTION_B_NAME))
|
|
has_collection_b = TRUE;
|
|
if (g_str_equal (wp_collection_get_name (c), COLLECTION_C_NAME))
|
|
has_collection_c = TRUE;
|
|
count++;
|
|
g_value_unset (&val);
|
|
}
|
|
|
|
g_assert_true (has_collection_a);
|
|
g_assert_true (has_collection_b);
|
|
g_assert_true (has_collection_c);
|
|
g_assert_cmpuint (count, ==, 3);
|
|
}
|
|
|
|
/* Make sure collection C was added */
|
|
g_assert_true (wp_collection_manager_has_collection (self->collection_manager,
|
|
COLLECTION_C_NAME));
|
|
|
|
/* Destroy collection C */
|
|
g_assert_true (wp_collection_manager_destroy_collection (
|
|
self->collection_manager, COLLECTION_C_NAME));
|
|
|
|
/* Make sure the manager has 2 collections */
|
|
g_assert_cmpuint (wp_collection_manager_get_collection_count (
|
|
self->collection_manager), ==, 2);
|
|
|
|
/* Make sure collection C was removed */
|
|
g_assert_false (wp_collection_manager_has_collection (self->collection_manager,
|
|
COLLECTION_C_NAME));
|
|
|
|
/* Remove collections A and B */
|
|
g_assert_true (wp_collection_manager_destroy_collection (
|
|
self->collection_manager, COLLECTION_A_NAME));
|
|
g_assert_true (wp_collection_manager_destroy_collection (
|
|
self->collection_manager, COLLECTION_B_NAME));
|
|
|
|
/* Make sure the manager does not have any collections */
|
|
g_assert_cmpuint (wp_collection_manager_get_collection_count (
|
|
self->collection_manager), ==, 0);
|
|
|
|
/* Make sure collections A and B were removed */
|
|
g_assert_false (wp_collection_manager_has_collection (self->collection_manager,
|
|
COLLECTION_A_NAME));
|
|
g_assert_false (wp_collection_manager_has_collection (self->collection_manager,
|
|
COLLECTION_B_NAME));
|
|
}
|
|
|
|
static void
|
|
test_collection_manager_global (TestCollectionManagerFixture *self,
|
|
gconstpointer d)
|
|
{
|
|
g_autoptr (WpGlobalProxy) global_a = NULL;
|
|
g_autoptr (WpGlobalProxy) global_b = NULL;
|
|
|
|
/* Activate global A */
|
|
global_a = WP_GLOBAL_PROXY (wp_impl_metadata_new_full (self->base.core,
|
|
"global-a", NULL));
|
|
wp_object_activate (WP_OBJECT (global_a), WP_OBJECT_FEATURES_ALL, NULL,
|
|
(GAsyncReadyCallback)on_metadata_activated, self);
|
|
g_main_loop_run (self->base.loop);
|
|
|
|
/* Activate global B */
|
|
global_b = WP_GLOBAL_PROXY (wp_impl_metadata_new_full (self->base.core,
|
|
"global-a", NULL));
|
|
wp_object_activate (WP_OBJECT (global_b), WP_OBJECT_FEATURES_ALL, NULL,
|
|
(GAsyncReadyCallback)on_metadata_activated, self);
|
|
g_main_loop_run (self->base.loop);
|
|
|
|
/* Make sure collection A and B don't have any globals */
|
|
g_assert_cmpuint (wp_collection_get_global_count (self->collection_a), ==, 0);
|
|
g_assert_cmpuint (wp_collection_get_global_count (self->collection_b), ==, 0);
|
|
|
|
/* Make sure global A and B don't belong to any collection */
|
|
g_assert_false (wp_collection_manager_is_global_collected (
|
|
self->collection_manager, global_a, NULL));
|
|
g_assert_false (wp_collection_manager_is_global_collected (
|
|
self->collection_manager, global_b, NULL));
|
|
|
|
/* Collect global A into collection A and global B into collection B */
|
|
g_assert_true (wp_collection_manager_collect_global (self->collection_manager,
|
|
global_a, COLLECTION_A_NAME));
|
|
g_assert_true (wp_collection_manager_collect_global (self->collection_manager,
|
|
global_b, COLLECTION_B_NAME));
|
|
|
|
/* Make sure collection A and B have only one global */
|
|
g_assert_cmpuint (wp_collection_get_global_count (self->collection_a), ==, 1);
|
|
g_assert_cmpuint (wp_collection_get_global_count (self->collection_b), ==, 1);
|
|
|
|
/* Iterate collection A */
|
|
{
|
|
g_autoptr (WpIterator) iter = NULL;
|
|
g_auto (GValue) val = G_VALUE_INIT;
|
|
guint count = 0;
|
|
|
|
iter = wp_collection_manager_new_global_iterator (self->collection_manager,
|
|
COLLECTION_A_NAME);
|
|
g_assert_nonnull (iter);
|
|
|
|
while (wp_iterator_next (iter, &val)) {
|
|
WpGlobalProxy *g = g_value_get_object (&val);
|
|
g_assert_nonnull (g);
|
|
g_assert_true (g == global_a);
|
|
count++;
|
|
g_value_unset (&val);
|
|
}
|
|
|
|
g_assert_cmpuint (count, ==, 1);
|
|
}
|
|
|
|
/* Iterate collection B */
|
|
{
|
|
g_autoptr (WpIterator) iter = NULL;
|
|
g_auto (GValue) val = G_VALUE_INIT;
|
|
guint count = 0;
|
|
|
|
iter = wp_collection_manager_new_global_iterator (self->collection_manager,
|
|
COLLECTION_B_NAME);
|
|
g_assert_nonnull (iter);
|
|
|
|
while (wp_iterator_next (iter, &val)) {
|
|
WpGlobalProxy *g = g_value_get_object (&val);
|
|
g_assert_nonnull (g);
|
|
g_assert_true (g == global_b);
|
|
count++;
|
|
g_value_unset (&val);
|
|
}
|
|
|
|
g_assert_cmpuint (count, ==, 1);
|
|
}
|
|
|
|
/* Make sure global A and global B are in their respective collection */
|
|
g_assert_true (wp_collection_manager_is_global_collected (
|
|
self->collection_manager, global_a, COLLECTION_A_NAME));
|
|
g_assert_true (wp_collection_manager_is_global_collected (
|
|
self->collection_manager, global_b, COLLECTION_B_NAME));
|
|
{
|
|
g_autoptr (WpCollection) ca = NULL;
|
|
g_autoptr (WpCollection) cb = NULL;
|
|
ca = wp_collection_manager_get_global_collection (self->collection_manager,
|
|
global_a);
|
|
g_assert_true (ca == self->collection_a);
|
|
cb = wp_collection_manager_get_global_collection (self->collection_manager,
|
|
global_b);
|
|
g_assert_true (cb == self->collection_b);
|
|
}
|
|
|
|
g_assert_true (WP_IS_COLLECTION (self->collection_a));
|
|
|
|
/* Make sure we cannot add global A into collection B and vice versa */
|
|
g_assert_false (wp_collection_manager_collect_global (
|
|
self->collection_manager, global_a, COLLECTION_B_NAME));
|
|
g_assert_false (wp_collection_manager_collect_global (
|
|
self->collection_manager, global_b, COLLECTION_A_NAME));
|
|
|
|
/* Drop global A from collection A */
|
|
g_assert_true (wp_collection_manager_drop_global (self->collection_manager,
|
|
global_a));
|
|
|
|
/* Make sure collection A does not have any globals */
|
|
g_assert_cmpuint (wp_collection_get_global_count (self->collection_a), ==, 0);
|
|
|
|
/* Make sure global A does not belong to any collection */
|
|
g_assert_false (wp_collection_manager_is_global_collected (
|
|
self->collection_manager, global_a, NULL));
|
|
|
|
/* Make sure collection A was automatically removed */
|
|
g_assert_false (wp_collection_manager_has_collection (
|
|
self->collection_manager, COLLECTION_A_NAME));
|
|
|
|
/* Collect global A into collection B */
|
|
g_assert_true (wp_collection_manager_collect_global (self->collection_manager,
|
|
global_a, COLLECTION_B_NAME));
|
|
|
|
/* Make sure global A is in collection B */
|
|
g_assert_true (wp_collection_manager_is_global_collected (
|
|
self->collection_manager, global_a, COLLECTION_B_NAME));
|
|
|
|
/* Make sure collection B has 2 globals */
|
|
g_assert_cmpuint (wp_collection_get_global_count (self->collection_b), ==, 2);
|
|
|
|
/* Iterate collection B */
|
|
{
|
|
g_autoptr (WpIterator) iter = NULL;
|
|
g_auto (GValue) val = G_VALUE_INIT;
|
|
gboolean has_global_a = FALSE;
|
|
gboolean has_global_b = FALSE;
|
|
guint count = 0;
|
|
|
|
iter = wp_collection_manager_new_global_iterator (self->collection_manager,
|
|
COLLECTION_B_NAME);
|
|
g_assert_nonnull (iter);
|
|
|
|
while (wp_iterator_next (iter, &val)) {
|
|
WpGlobalProxy *g = g_value_get_object (&val);
|
|
g_assert_nonnull (g);
|
|
if (g == global_a)
|
|
has_global_a = TRUE;
|
|
if (g == global_b)
|
|
has_global_b = TRUE;
|
|
count++;
|
|
g_value_unset (&val);
|
|
}
|
|
|
|
g_assert_true (has_global_a);
|
|
g_assert_true (has_global_b);
|
|
g_assert_cmpuint (count, ==, 2);
|
|
}
|
|
|
|
/* Drop global B from collection B */
|
|
g_assert_true (wp_collection_manager_drop_global (self->collection_manager,
|
|
global_b));
|
|
|
|
/* Make sure collection B has only one global */
|
|
g_assert_cmpuint (wp_collection_get_global_count (self->collection_b), ==, 1);
|
|
|
|
/* Make sure global B does not belong to any collection */
|
|
g_assert_false (wp_collection_manager_is_global_collected (
|
|
self->collection_manager, global_b, NULL));
|
|
|
|
/* Drop global A from collection B */
|
|
g_assert_true (wp_collection_manager_drop_global (self->collection_manager,
|
|
global_a));
|
|
|
|
/* Make sure collection B does not have any globals */
|
|
g_assert_cmpuint (wp_collection_get_global_count (self->collection_b), ==, 0);
|
|
|
|
/* Make sure global A does not belong to any collection */
|
|
g_assert_false (wp_collection_manager_is_global_collected (
|
|
self->collection_manager, global_a, NULL));
|
|
|
|
/* Make sure collection B was automatically removed */
|
|
g_assert_false (wp_collection_manager_has_collection (
|
|
self->collection_manager, COLLECTION_B_NAME));
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
g_test_init (&argc, &argv, NULL);
|
|
wp_init (WP_INIT_ALL);
|
|
|
|
g_test_add ("/wp/collection-manager/collection",
|
|
TestCollectionManagerFixture, NULL, collection_manager_setup,
|
|
test_collection_manager_collection, collection_manager_teardown);
|
|
g_test_add ("/wp/collection-manager/global",
|
|
TestCollectionManagerFixture, NULL, collection_manager_setup,
|
|
test_collection_manager_global, collection_manager_teardown);
|
|
|
|
return g_test_run ();
|
|
}
|