From: Youngjae Cho Date: Fri, 6 Oct 2023 07:23:04 +0000 (+0900) Subject: resource-manager: Add API for fine-tuned event listening X-Git-Tag: accepted/tizen/8.0/unified/20231123.173029~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=69bdd0e59e3effe630388e3bf0e5af2fc67c83fe;p=platform%2Fcore%2Fsystem%2Flibsyscommon.git resource-manager: Add API for fine-tuned event listening The syscommon_resman_subscribe_resource_event() has been split into 3 variants, each of which can narrow down the range of events that we want to listen to. - syscommon_resman_subscribe_event(...) : It is identical to the existing one. Listen any events from any type of resources. - syscommon_resman_subscribe_resource_event(resource_type, ...) : Listen any changes of attribute from specific type of resources. - syscommon_resman_subscribe_resource_attribute_event(resource_type, attr_mask, ...) : Listen change of specific attributes from specific type of resources. In addition, the event callback has been changed to receive an additional parameter, void *user_data. Change-Id: I41876fa746d1d042bc1595db55d29e3b8ff13e86 Signed-off-by: Youngjae Cho --- diff --git a/include/libsyscommon/resource-manager.h b/include/libsyscommon/resource-manager.h index d6d3264..efac317 100644 --- a/include/libsyscommon/resource-manager.h +++ b/include/libsyscommon/resource-manager.h @@ -250,10 +250,15 @@ int syscommon_resman_unset_resource_attr_interest(int resource_id, u_int64_t int bool syscommon_resman_is_resource_attr_interested(int resource_id, u_int64_t interest_mask); typedef void (*syscommon_resman_resource_event_cb) (int resource_type, - int resource_id, int attr_id, const void *data, int count); - -int syscommon_resman_subscribe_resource_event(syscommon_resman_resource_event_cb callback, int *id); -void syscommon_resman_unsubscribe_resource_event(int id); + int resource_id, int attr_id, const void *data, void *user_data, int count); + +int syscommon_resman_subscribe_resource_attribute_event(int resource_type, + u_int64_t attr_mask, syscommon_resman_resource_event_cb callback, void *user_data, int *id); +int syscommon_resman_subscribe_resource_event(int resource_type, + syscommon_resman_resource_event_cb callback, void *user_data, int *id); +int syscommon_resman_subscribe_event(syscommon_resman_resource_event_cb callback, + void *user_data, int *id); +void syscommon_resman_unsubscribe_event(int id); const char *syscommon_resman_get_resource_attr_name(int resource_id, u_int64_t attr_id); const char *syscommon_resman_get_resource_name(int resource_id); diff --git a/src/resource-manager/resource-manager.c b/src/resource-manager/resource-manager.c index 61fbe59..83b9da3 100644 --- a/src/resource-manager/resource-manager.c +++ b/src/resource-manager/resource-manager.c @@ -41,6 +41,9 @@ #define INSTANCE_TYPE_NORMAL 0 #define INSTANCE_TYPE_MONITOR 1 +#define RESOURCE_TYPE_ALL (-1) +#define RESOURCE_ATTR_ALL (~0ULL) + struct syscommon_resman_resource { char *name; int id; @@ -72,14 +75,17 @@ struct attribute_is_supported_ops { struct resource_event_data { int id; + int resource_type; + int attr_mask; syscommon_resman_resource_event_cb callback; + void *user_data; }; static int set_resource_attr_interest(struct syscommon_resman_resource *resource, u_int64_t interest_mask); static int unset_resource_attr_interest(struct syscommon_resman_resource *resource, u_int64_t interest_mask); static bool is_resource_attr_interested(struct syscommon_resman_resource *resource, u_int64_t interest_mask); static void -notify_resource_event(int resource_type, int resource_id, int attr_id, const void *data, int count); +notify_resource_event(int resource_type, int resource_id, u_int64_t attr_id, const void *data, int count); static GList *g_resource_driver_head; static GList *g_resource_event_data_list; @@ -1950,7 +1956,7 @@ syscommon_resman_is_resource_attr_interested(int resource_id, u_int64_t interest } static void -notify_resource_event(int resource_type, int resource_id, int attr_id, const void *data, int count) +notify_resource_event(int resource_type, int resource_id, u_int64_t attr_id, const void *data, int count) { GList *elem; struct resource_event_data *event_data; @@ -1959,7 +1965,14 @@ notify_resource_event(int resource_type, int resource_id, int attr_id, const voi event_data = (struct resource_event_data *) elem->data; assert(event_data); - event_data->callback(resource_type, resource_id, attr_id, data, count); + + if ((event_data->resource_type != RESOURCE_TYPE_ALL) && (event_data->resource_type != resource_type)) + continue; + + if ((event_data->attr_mask & attr_id) == 0) + continue; + + event_data->callback(resource_type, resource_id, attr_id, data, event_data->user_data, count); } } @@ -1971,8 +1984,8 @@ static gboolean find_resource_event_data(gconstpointer data, gconstpointer id) return (_event_data->id - _id); } -int -syscommon_resman_subscribe_resource_event(syscommon_resman_resource_event_cb callback, int *id) +int syscommon_resman_subscribe_resource_attribute_event(int resource_type, + u_int64_t attr_mask, syscommon_resman_resource_event_cb callback, void *user_data, int *id) { struct resource_event_data *event_data = NULL; @@ -1985,7 +1998,10 @@ syscommon_resman_subscribe_resource_event(syscommon_resman_resource_event_cb cal *event_data = (struct resource_event_data) { .id = alloc_resource_id(), - .callback = callback + .resource_type = resource_type, + .attr_mask = attr_mask, + .callback = callback, + .user_data = user_data, }; g_resource_event_data_list = g_list_append(g_resource_event_data_list, event_data); @@ -1995,7 +2011,20 @@ syscommon_resman_subscribe_resource_event(syscommon_resman_resource_event_cb cal return 0; } -void syscommon_resman_unsubscribe_resource_event(int id) +int syscommon_resman_subscribe_resource_event(int resource_type, + syscommon_resman_resource_event_cb callback, void *user_data, int *id) +{ + return syscommon_resman_subscribe_resource_attribute_event(resource_type, + RESOURCE_ATTR_ALL, callback, user_data, id); +} + +int syscommon_resman_subscribe_event(syscommon_resman_resource_event_cb callback, + void *user_data, int *id) +{ + return syscommon_resman_subscribe_resource_event(RESOURCE_TYPE_ALL, callback, user_data, id); +} + +void syscommon_resman_unsubscribe_event(int id) { GList *list; diff --git a/tests/resource-manager/battery-interface.h b/tests/resource-manager/battery-interface.h new file mode 100644 index 0000000..dd4bfb4 --- /dev/null +++ b/tests/resource-manager/battery-interface.h @@ -0,0 +1,7 @@ +#ifndef __BATTERY_INTERFACE_H__ +#define __BATTERY_INTERFACE_H__ + +#define BATTERY_ATTR_INT (1ULL << 0) +#define BATTERY_ATTR_UINT (1ULL << 1) + +#endif /* __BATTERY_INTERFACE_H__ */ diff --git a/tests/resource-manager/common-interface.h b/tests/resource-manager/common-interface.h index b47baaf..2876175 100644 --- a/tests/resource-manager/common-interface.h +++ b/tests/resource-manager/common-interface.h @@ -1,9 +1,23 @@ #ifndef __TEST_COMMON_INTERFACE_H__ #define __TEST_COMMON_INTERFACE_H__ +#include +#include + enum libsyscommon_test_resource_type { TEST_RESOURCE_TYPE_DISPLAY, + TEST_RESOURCE_TYPE_BATTERY, TEST_RESOURCE_TYPE_NOT_EXIST, }; +typedef union { + int32_t i32; + int64_t i64; + uint32_t u32; + uint64_t u64; + double d; + void* p; + bool b; +} resource_attr_data_t; + #endif /* __TEST_COMMON_INTERFACE_H__ */ diff --git a/tests/resource-manager/resource-battery.c b/tests/resource-manager/resource-battery.c new file mode 100644 index 0000000..9de225e --- /dev/null +++ b/tests/resource-manager/resource-battery.c @@ -0,0 +1,132 @@ +#include + +#include +#include + +#include "common-interface.h" +#include "battery-interface.h" +#include "../test-main.h" + +static int test_battery_get(int resource_id, + const struct syscommon_resman_resource_attribute *attr, + void *data) +{ + int ret = 0; + resource_attr_data_t attr_data = { 0, }; + + switch (attr->id) { + case BATTERY_ATTR_INT: + attr_data.i32 = mock_type(int); + break; + case BATTERY_ATTR_UINT: + attr_data.u32 = mock_type(uint32_t); + break; + default: + return -EINVAL; + } + + ret = mock_type(int); + + if (ret < 0) + return ret; + + switch (attr->type) { + case SYSCOMMON_RESMAN_DATA_TYPE_INT: + *(int32_t *) data = attr_data.i32; + break; + case SYSCOMMON_RESMAN_DATA_TYPE_INT64: + *(int64_t *) data = attr_data.i64; + break; + case SYSCOMMON_RESMAN_DATA_TYPE_UINT: + *(uint32_t *) data = attr_data.u32; + break; + case SYSCOMMON_RESMAN_DATA_TYPE_UINT64: + *(uint64_t *) data = attr_data.u64; + break; + case SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE: + *(double *) data = attr_data.d; + break; + case SYSCOMMON_RESMAN_DATA_TYPE_PTR: + *(void **) data = attr_data.p; + break; + case SYSCOMMON_RESMAN_DATA_TYPE_BOOLEAN: + *(bool *) data = attr_data.b; + break; + default: + return -EINVAL; + } + + return ret; +} + +static int test_battery_set(int resource_id, + const struct syscommon_resman_resource_attribute *attr, + const void *data, int count) +{ + check_expected_ptr(data); + + return mock_type(int); +} + +static const struct syscommon_resman_resource_attribute battery_attrs[] = { + { + .name = "BATTERY_ATTR_INT", + .id = BATTERY_ATTR_INT, + .type = SYSCOMMON_RESMAN_DATA_TYPE_INT, + .flag = SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC, + .ops = { + .get = test_battery_get, + .set = test_battery_set, + .is_supported = syscommon_resman_resource_attr_supported_always, + }, + } ,{ + .name = "BATTERY_ATTR_UINT", + .id = BATTERY_ATTR_UINT, + .type = SYSCOMMON_RESMAN_DATA_TYPE_UINT, + .flag = SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC, + .ops = { + .get = test_battery_get, + .set = test_battery_set, + .is_supported = syscommon_resman_resource_attr_supported_always, + }, + } +}; + +static const struct syscommon_resman_resource_driver battery_resource_driver = { + .name = "test-battery", + .type = TEST_RESOURCE_TYPE_BATTERY, + .flag = SYSCOMMON_RESMAN_RESOURCE_DRIVER_FLAG_COUNT_ONLY_ONE, + .attrs = battery_attrs, + .num_attrs = sizeof(battery_attrs)/sizeof(battery_attrs[0]), +}; + +int create_battery_resource(void) +{ + int resource_id; + int ret; + + ret = syscommon_resman_create_resource(&resource_id, TEST_RESOURCE_TYPE_BATTERY); + assert_int_equal(ret, 0); + + return resource_id; +} + +void delete_battery_resource(int resource_id) +{ + syscommon_resman_delete_resource(resource_id); +} + +void setup_battery_resource_driver(void) +{ + /** + * Instead of using macro SYSCOMMON_RESMAN_RESOURCE_DRIVER_REGISTER(), + * use function. + * + * There two macros, SYSCOMMON_RESMAN_RESOURCE_DRIVER_REGISTER() and TESTSUITE(), + * are both using __attribute__((constructor)). And its order cannot be explicitly + * specified. However, the SYSCOMMON_RESMAN_RESOURCE_DRIVER_REGISTER() must be followed + * by the TESTSUITE(). Therefore, explicitly registers the driver via setup function + * prior to the execution of the testsuite. + */ + syscommon_resman_add_resource_driver(&battery_resource_driver); +} diff --git a/tests/resource-manager/resource-battery.h b/tests/resource-manager/resource-battery.h new file mode 100644 index 0000000..8426b6c --- /dev/null +++ b/tests/resource-manager/resource-battery.h @@ -0,0 +1,9 @@ +#ifndef __RESOURCE_BATTERY_H__ +#define __RESOURCE_BATTERY_H__ + +int create_battery_resource(void); +void delete_battery_resource(int resource_id); +void setup_battery_resource_driver(void); + +#endif /* __RESOURCE_BATTERY_H__ */ + diff --git a/tests/resource-manager/resource-display.c b/tests/resource-manager/resource-display.c index 570115c..795a72a 100644 --- a/tests/resource-manager/resource-display.c +++ b/tests/resource-manager/resource-display.c @@ -1,5 +1,4 @@ #include -#include #include #include @@ -8,16 +7,6 @@ #include "display-interface.h" #include "../test-main.h" -typedef union { - int32_t i32; - int64_t i64; - uint32_t u32; - uint64_t u64; - double d; - void* p; - bool b; -} resource_attr_data_t; - static int display_resource_driver_create(int resource_id) { return mock_type(int); diff --git a/tests/resource-manager/test.c b/tests/resource-manager/test.c index 00d205b..a8bc52a 100644 --- a/tests/resource-manager/test.c +++ b/tests/resource-manager/test.c @@ -2,10 +2,21 @@ #include "common-interface.h" #include "display-interface.h" +#include "battery-interface.h" #include "resource-display.h" +#include "resource-battery.h" + #include "../test-main.h" +static int setup_resource_drivers(void **state) +{ + setup_display_resource_driver(); + setup_battery_resource_driver(); + + return 0; +} + static void test_create_resource_pass(void **state) { int resource_id; @@ -364,7 +375,7 @@ static void test_set_resource_attr_int_fail_invalid_parameter_1(void **state) delete_display_resource(resource_id); } -static void test_event_callback1(int resource_type, int resource_id, int attr_id, const void *data, int count) +static void test_event_callback1(int resource_type, int resource_id, int attr_id, const void *data, void *user_data, int count) { check_expected(resource_type); check_expected(resource_id); @@ -373,7 +384,7 @@ static void test_event_callback1(int resource_type, int resource_id, int attr_id check_expected(count); } -static void test_event_callback2(int resource_type, int resource_id, int attr_id, const void *data, int count) +static void test_event_callback2(int resource_type, int resource_id, int attr_id, const void *data, void *user_data, int count) { check_expected(resource_type); check_expected(resource_id); @@ -395,7 +406,7 @@ static void test_subscribe_event_pass(void **state) resource_id1 = create_display_resource(); resource_id2 = create_display_resource(); - ret = syscommon_resman_subscribe_resource_event(test_event_callback1, &callback_id1); + ret = syscommon_resman_subscribe_event(test_event_callback1, NULL, &callback_id1); assert_int_equal(ret, 0); /* configure mock setter, success */ @@ -412,7 +423,7 @@ static void test_subscribe_event_pass(void **state) assert_int_equal(ret, 0); /* register additional callback2 */ - ret = syscommon_resman_subscribe_resource_event(test_event_callback2, &callback_id2); + ret = syscommon_resman_subscribe_event(test_event_callback2, NULL, &callback_id2); assert_int_equal(ret, 0); /* second try, configure mock setter, success */ @@ -436,7 +447,7 @@ static void test_subscribe_event_pass(void **state) assert_int_equal(ret, 0); /* unregister the callback1 */ - syscommon_resman_unsubscribe_resource_event(callback_id1); + syscommon_resman_unsubscribe_event(callback_id1); /* third try, configure mock setter, success */ int_value = 10101; @@ -453,7 +464,7 @@ static void test_subscribe_event_pass(void **state) assert_int_equal(ret, 0); /* unregister the callback2 */ - syscommon_resman_unsubscribe_resource_event(callback_id2); + syscommon_resman_unsubscribe_event(callback_id2); /* the last try, configure mock setter, success */ double_value = 5959.95; @@ -473,7 +484,7 @@ static void test_subscribe_event_fail_invalid_parameter_1(void **state) int callback_id; int ret; - ret = syscommon_resman_subscribe_resource_event(NULL, &callback_id); + ret = syscommon_resman_subscribe_event(NULL, NULL, &callback_id); assert_int_equal(ret, -EINVAL); } @@ -481,7 +492,7 @@ static void test_subscribe_event_fail_invalid_parameter_2(void **state) { int ret; - ret = syscommon_resman_subscribe_resource_event(test_event_callback1, NULL); + ret = syscommon_resman_subscribe_event(test_event_callback1, NULL, NULL); assert_int_equal(ret, -EINVAL); } @@ -494,7 +505,7 @@ static void test_subscribe_event_fail_setter(void **state) resource_id = create_display_resource(); - ret = syscommon_resman_subscribe_resource_event(test_event_callback1, &callback_id); + ret = syscommon_resman_subscribe_event(test_event_callback1, NULL, &callback_id); assert_int_equal(ret, 0); /* configure mock setter, fail */ @@ -505,16 +516,159 @@ static void test_subscribe_event_fail_setter(void **state) ret = syscommon_resman_set_resource_attr_int(resource_id, DISPLAY_ATTR_INT, value); assert_int_equal(ret, -ENOENT); - syscommon_resman_unsubscribe_resource_event(callback_id); + syscommon_resman_unsubscribe_event(callback_id); delete_display_resource(resource_id); } -static int setup_resource_drivers(void **state) +static void test_subscribe_resource_event_pass(void **state) { - setup_display_resource_driver(); + int display_resource_id; + int battery_resource_id; + int callback_id; + int int_value = -12345; + uint32_t uint_value = 494949; + int ret; - return 0; + display_resource_id = create_display_resource(); + battery_resource_id = create_battery_resource(); + + ret = syscommon_resman_subscribe_resource_event(TEST_RESOURCE_TYPE_BATTERY, + test_event_callback1, NULL, &callback_id); + assert_int_equal(ret, 0); + + /* Test 1: subscribe battery event, generate display event */ + /* configure display mock setter, success */ + expect_memory(test_display_set, data, &int_value, sizeof(int)); + will_return(test_display_set, 0); + /* do not configure mock callback as it is only invoked by battery setter */ + + ret = syscommon_resman_set_resource_attr_int(display_resource_id, DISPLAY_ATTR_INT, int_value); + assert_int_equal(ret, 0); + + /* Test 2: subscribe battery event, generate battery event BATTERY_ATTR_INT */ + /* configure battery mock setter, success */ + expect_memory(test_battery_set, data, &int_value, sizeof(int)); + will_return(test_battery_set, 0); + /* configure battery mock callback1 */ + expect_value(test_event_callback1, resource_type, TEST_RESOURCE_TYPE_BATTERY); + expect_value(test_event_callback1, resource_id, battery_resource_id); + expect_value(test_event_callback1, attr_id, BATTERY_ATTR_INT); + expect_memory(test_event_callback1, data, &int_value, sizeof(int)); + expect_value(test_event_callback1, count, 1); + + ret = syscommon_resman_set_resource_attr_int(battery_resource_id, BATTERY_ATTR_INT, int_value); + assert_int_equal(ret, 0); + + /* Test 3: subscribe battery event, generate battery event BATTERY_ATTR_UINT */ + /* configure battery mock setter, success */ + expect_memory(test_battery_set, data, &uint_value, sizeof(int)); + will_return(test_battery_set, 0); + /* configure battery mock callback1 */ + expect_value(test_event_callback1, resource_type, TEST_RESOURCE_TYPE_BATTERY); + expect_value(test_event_callback1, resource_id, battery_resource_id); + expect_value(test_event_callback1, attr_id, BATTERY_ATTR_UINT); + expect_memory(test_event_callback1, data, &uint_value, sizeof(uint32_t)); + expect_value(test_event_callback1, count, 1); + + ret = syscommon_resman_set_resource_attr_uint(battery_resource_id, BATTERY_ATTR_UINT, uint_value); + assert_int_equal(ret, 0); + + syscommon_resman_unsubscribe_event(callback_id); + delete_display_resource(display_resource_id); + delete_battery_resource(battery_resource_id); +} + +static void test_subscribe_resource_event_fail_invalid_parameter_1(void **state) +{ + int ret; + int callback_id; + + ret = syscommon_resman_subscribe_resource_event(TEST_RESOURCE_TYPE_BATTERY, + NULL, NULL, &callback_id); + assert_int_equal(ret, -EINVAL); +} + +static void test_subscribe_resource_event_fail_invalid_parameter_2(void **state) +{ + int ret; + + ret = syscommon_resman_subscribe_resource_event(TEST_RESOURCE_TYPE_BATTERY, + test_event_callback1, NULL, NULL); + assert_int_equal(ret, -EINVAL); +} + +static void test_subscribe_resource_attribute_event_pass(void **state) +{ + int display_resource_id; + int battery_resource_id; + int callback_id; + int int_value = -12345; + uint32_t uint_value = 494949; + double double_value = -100.001; + int ret; + + display_resource_id = create_display_resource(); + battery_resource_id = create_battery_resource(); + + ret = syscommon_resman_subscribe_resource_attribute_event(TEST_RESOURCE_TYPE_DISPLAY, + DISPLAY_ATTR_INT | DISPLAY_ATTR_DOUBLE, test_event_callback1, NULL, &callback_id); + assert_int_equal(ret, 0); + + /* Test 1: subscribe display event, generate battery event */ + /* configure battery mock setter, success */ + expect_memory(test_battery_set, data, &int_value, sizeof(int)); + will_return(test_battery_set, 0); + /* do not configure mock callback as it is only invoked by display setter */ + + ret = syscommon_resman_set_resource_attr_int(battery_resource_id, BATTERY_ATTR_INT, int_value); + assert_int_equal(ret, 0); + + /* Test 2: subscribe display event, generate display event that we aren't interested in */ + /* configure display mock setter, success */ + expect_memory(test_display_set, data, &uint_value, sizeof(uint32_t)); + will_return(test_display_set, 0); + /* do not configure mock callback as it is not interesting display event*/ + + ret = syscommon_resman_set_resource_attr_uint(display_resource_id, DISPLAY_ATTR_UINT, uint_value); + assert_int_equal(ret, 0); + + /* Test 3: subscribe display event, generate display event that we are interested in */ + /* configure display mock setter, success */ + expect_memory(test_display_set, data, &double_value, sizeof(double)); + will_return(test_display_set, 0); + /* configure display mock callback1 */ + expect_value(test_event_callback1, resource_type, TEST_RESOURCE_TYPE_DISPLAY); + expect_value(test_event_callback1, resource_id, display_resource_id); + expect_value(test_event_callback1, attr_id, DISPLAY_ATTR_DOUBLE); + expect_memory(test_event_callback1, data, &double_value, sizeof(double)); + expect_value(test_event_callback1, count, 1); + + ret = syscommon_resman_set_resource_attr_double(display_resource_id, DISPLAY_ATTR_DOUBLE, double_value); + assert_int_equal(ret, 0); + + syscommon_resman_unsubscribe_event(callback_id); + delete_display_resource(display_resource_id); + delete_battery_resource(battery_resource_id); +} + +static void test_subscribe_resource_attribute_event_fail_invalid_parameter_1(void **state) +{ + int ret; + int callback_id; + + ret = syscommon_resman_subscribe_resource_attribute_event(TEST_RESOURCE_TYPE_BATTERY, + BATTERY_ATTR_INT, NULL, NULL, &callback_id); + assert_int_equal(ret, -EINVAL); +} + +static void test_subscribe_resource_attribute_event_fail_invalid_parameter_2(void **state) +{ + int ret; + + ret = syscommon_resman_subscribe_resource_attribute_event(TEST_RESOURCE_TYPE_BATTERY, + BATTERY_ATTR_INT, test_event_callback1, NULL, NULL); + assert_int_equal(ret, -EINVAL); } static const struct CMUnitTest resource_manager_testsuite[] = { @@ -547,5 +701,13 @@ static const struct CMUnitTest resource_manager_testsuite[] = { cmocka_unit_test(test_subscribe_event_fail_invalid_parameter_1), cmocka_unit_test(test_subscribe_event_fail_invalid_parameter_2), cmocka_unit_test(test_subscribe_event_fail_setter), + + cmocka_unit_test(test_subscribe_resource_event_pass), + cmocka_unit_test(test_subscribe_resource_event_fail_invalid_parameter_1), + cmocka_unit_test(test_subscribe_resource_event_fail_invalid_parameter_2), + + cmocka_unit_test(test_subscribe_resource_attribute_event_pass), + cmocka_unit_test(test_subscribe_resource_attribute_event_fail_invalid_parameter_1), + cmocka_unit_test(test_subscribe_resource_attribute_event_fail_invalid_parameter_2), }; TESTSUITE_FIXTURE(resource_manager_testsuite, setup_resource_drivers, NULL);