wireplumber/tests/wp/collection-manager.c
Julian Bouzas a3803de00b lib: Add new WpCollectionManager API
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.
2026-04-08 16:18:45 -04:00

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 ();
}