mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2025-12-20 09:10:04 +01:00
util: add support for parametrized tests
munit supports test parameters (char* only) but the setup is a big
awkward/impossible in C to define statically. So lets simply pass the
parameters as one NULL-terminated string list and require names to be
prefixed with an @. During the test setup we can split that list up into
multiple parameters and pass those to the munit setup where they're
accessible via another wrapper macro:
MUNIT_TEST_WITH_PARAMS(test_foo, "@x", "1", "2", "@y", "100", "200") {
const char *x = MUNIT_TEST_PARAM("@x");
const char *y = MUNIT_TEST_PARAM("@y");
}
Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/365>
This commit is contained in:
parent
d55da9466c
commit
2996a66b37
2 changed files with 64 additions and 1 deletions
|
|
@ -56,10 +56,42 @@ munit_tests_run(int argc, char **argv)
|
||||||
_cleanup_free_ MunitTest *tests = calloc(count, sizeof(*tests));
|
_cleanup_free_ MunitTest *tests = calloc(count, sizeof(*tests));
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
foreach_test(t) {
|
foreach_test(t) {
|
||||||
|
size_t nparams = 0;
|
||||||
|
MunitParameterEnum *parameters = calloc(MUNIT_TEST_MAX_PARAMS, sizeof(*parameters));
|
||||||
|
|
||||||
|
const char *name = NULL;
|
||||||
|
char **values = NULL;
|
||||||
|
for (size_t i = 0; t->params[i]; i++) {
|
||||||
|
if (t->params[i][0] == '@') {
|
||||||
|
if (name != NULL) {
|
||||||
|
assert(nparams < MUNIT_TEST_MAX_PARAMS);
|
||||||
|
assert(strv_len(values) > 0);
|
||||||
|
/* Not stripping the @! */
|
||||||
|
parameters[nparams].name = xstrdup(name);
|
||||||
|
parameters[nparams].values = steal(&values);
|
||||||
|
++nparams;
|
||||||
|
}
|
||||||
|
name = t->params[i];
|
||||||
|
} else {
|
||||||
|
assert(i > 0); /* First one must be a name */
|
||||||
|
values = strv_append_strdup(values, t->params[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name != NULL) {
|
||||||
|
assert(nparams < MUNIT_TEST_MAX_PARAMS);
|
||||||
|
assert(strv_len(values) > 0);
|
||||||
|
/* Not stripping the @! */
|
||||||
|
parameters[nparams].name = xstrdup(name);
|
||||||
|
parameters[nparams].values = steal(&values);
|
||||||
|
++nparams;
|
||||||
|
}
|
||||||
|
|
||||||
MunitTest test = {
|
MunitTest test = {
|
||||||
.name = xaprintf("%s", t->name),
|
.name = xaprintf("%s", t->name),
|
||||||
.test = t->func,
|
.test = t->func,
|
||||||
|
.parameters = parameters,
|
||||||
};
|
};
|
||||||
|
|
||||||
tests[idx++] = test;
|
tests[idx++] = test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,8 +123,10 @@ munit_tests_run(int argc, char **argv)
|
||||||
|
|
||||||
int rc = munit_suite_main(&suite, setup.userdata, setup.argc, setup.argv);
|
int rc = munit_suite_main(&suite, setup.userdata, setup.argc, setup.argv);
|
||||||
|
|
||||||
for (idx = 0; idx < count; idx++)
|
for (idx = 0; idx < count; idx++) {
|
||||||
free(tests[idx].name);
|
free(tests[idx].name);
|
||||||
|
free(tests[idx].parameters);
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,9 @@
|
||||||
|
|
||||||
#include <munit.h>
|
#include <munit.h>
|
||||||
|
|
||||||
|
/* Random number, bumb if need be */
|
||||||
|
#define MUNIT_TEST_MAX_PARAMS 64
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Put at the top of the file somewhere, declares the start/stop for the test section we need.
|
* Put at the top of the file somewhere, declares the start/stop for the test section we need.
|
||||||
*/
|
*/
|
||||||
|
|
@ -61,6 +64,7 @@ struct test_function {
|
||||||
const char *name; /* function name */
|
const char *name; /* function name */
|
||||||
const char *file; /* file name */
|
const char *file; /* file name */
|
||||||
munit_test_func_t func; /* test function */
|
munit_test_func_t func; /* test function */
|
||||||
|
const char *params[MUNIT_TEST_MAX_PARAMS];
|
||||||
} __attribute__((aligned(16)));
|
} __attribute__((aligned(16)));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -104,9 +108,34 @@ __attribute__((section("test_functions_section"))) = { \
|
||||||
.name = #_func, \
|
.name = #_func, \
|
||||||
.func = _func, \
|
.func = _func, \
|
||||||
.file = __FILE__, \
|
.file = __FILE__, \
|
||||||
|
.params = { NULL }, \
|
||||||
}; \
|
}; \
|
||||||
static MunitResult _func(const MunitParameter params[], void *user_data)
|
static MunitResult _func(const MunitParameter params[], void *user_data)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as MUNIT test but takes a list of strings that define parameters
|
||||||
|
* and their values. Parameter names must be prefixed with @, for example:
|
||||||
|
* MUNIT_TEST_WITH_PARAMS(test_foo, "@x", "1", "2", "@y", "100", "200") {
|
||||||
|
* const char *x = MUNIT_TEST_PARAM("@x");
|
||||||
|
* const char *y = MUNIT_TEST_PARAM("@y");
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
#define MUNIT_TEST_WITH_PARAMS(_func, ...) \
|
||||||
|
static MunitResult _func(const MunitParameter params[], void *user_data); \
|
||||||
|
static const struct test_function _test_##_func \
|
||||||
|
__attribute__((used)) \
|
||||||
|
__attribute__((section("test_functions_section"))) = { \
|
||||||
|
.name = #_func, \
|
||||||
|
.func = _func, \
|
||||||
|
.file = __FILE__, \
|
||||||
|
.params = { __VA_ARGS__, NULL }, \
|
||||||
|
}; \
|
||||||
|
static MunitResult _func(const MunitParameter params[], void *user_data)
|
||||||
|
|
||||||
|
/* Retrieve the test parameter with the given name */
|
||||||
|
#define MUNIT_TEST_PARAM(name_) \
|
||||||
|
munit_parameters_get(params, name_)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a struct global_setup_function in a custom ELF section that we can
|
* Defines a struct global_setup_function in a custom ELF section that we can
|
||||||
* then find in munit_tests_run() to do setup based on argv and/or pass userdata
|
* then find in munit_tests_run() to do setup based on argv and/or pass userdata
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue