mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-20 12:40:05 +01:00
test: implement support for parametrizing tests
litest supports ranged tests but they are not enough, doubly so with
tests where we want to parametrize across multiple options.
This patch adds support for just that, in clunky C style.
The typical invocation for a test is by giving the test parameter
a name, a number of values and then the values themselves:
struct litest_parameters *params = litest_parameters_new("axis", 's', 2, "ABS_X", "ABS_Y",
"enabled", 'b', '2', true, false,
"number", 'u', '2', 10, 11,
NULL);
litest_add_parametrized(sometest, LITEST_ANY, LITEST_ANY, params);
litest_parameters_unref(params);
Currently supported are u (uint32), i (int32), d (double), b (bool),
c (char) and s (string).
In the test itself, the `test_env->params` variable is available and
retrieval of the parameters works like this:
const char *axis;
uint32_t number;
bool enabled;
litest_test_param_fetch(test_env->params,
"axis", &axis,
"enabled", &enabled,
"number", &number,
NULL);
Note that since this is an effectively internal test-suite only
functionality we don't do type-checking here, it's assumed that if you
write the code to pass parameters into a test you remember the type
of said params when you write the test code.
Because we don't have hashmaps or anything useful other than lists the
implementation is a bit clunky: we copy the parameter into the test
during litest_add_*, permutate it for our test list which gives us yet
another linked list C struct, and finally copy the actual value into
the test and test environment as it's executed. Not pretty, but it
works.
A few tests are switched as simple demonstration. The name of the
test has the parameters with their names and values appended now, e.g.:
"pointer:pointer_scroll_wheel_hires_send_only_lores:ms-surface-cover:axis:ABS_X"
"pointer:pointer_motion_relative_min_decel:mouse-roccat:direction:NW"
Filtering by parameters can be done via globs of their string
representation:
libinput-test-suite --filter-params="axis:ABS_*,enabled:true,number:10*"
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1109>
This commit is contained in:
parent
f9f9bccba2
commit
1e445f3f84
10 changed files with 1004 additions and 89 deletions
|
|
@ -44,6 +44,12 @@ struct multivalue {
|
||||||
static inline void
|
static inline void
|
||||||
multivalue_extract(const struct multivalue *v, void *ptr)
|
multivalue_extract(const struct multivalue *v, void *ptr)
|
||||||
{
|
{
|
||||||
|
/* ignore false positives from gcc:
|
||||||
|
* ../src/util-multivalue.h:52:33: warning: array subscript ‘double[0]’ is partly outside array bounds of ‘int32_t[1]’ {aka ‘int[1]’} [-Warray-bounds=]
|
||||||
|
* 52 | case 'd': *(double*)ptr = v->value.d; break;
|
||||||
|
*/
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||||
switch (v->type) {
|
switch (v->type) {
|
||||||
case 'b': *(bool *)ptr = v->value.b; break;
|
case 'b': *(bool *)ptr = v->value.b; break;
|
||||||
case 'c': *(char *)ptr = v->value.c; break;
|
case 'c': *(char *)ptr = v->value.c; break;
|
||||||
|
|
@ -54,6 +60,7 @@ multivalue_extract(const struct multivalue *v, void *ptr)
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
#include "util-files.h"
|
#include "util-files.h"
|
||||||
#include "util-list.h"
|
#include "util-list.h"
|
||||||
|
#include "util-multivalue.h"
|
||||||
#include "util-stringbuf.h"
|
#include "util-stringbuf.h"
|
||||||
|
|
||||||
static bool use_jmpbuf; /* only used for max_forks = 0 */
|
static bool use_jmpbuf; /* only used for max_forks = 0 */
|
||||||
|
|
@ -255,6 +256,7 @@ litest_runner_test_run(const struct litest_runner_test_description *desc)
|
||||||
{
|
{
|
||||||
const struct litest_runner_test_env env = {
|
const struct litest_runner_test_env env = {
|
||||||
.rangeval = desc->rangeval,
|
.rangeval = desc->rangeval,
|
||||||
|
.params = desc->params,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (desc->setup)
|
if (desc->setup)
|
||||||
|
|
@ -647,6 +649,59 @@ print_lines(FILE *fp, const char *log, const char *prefix)
|
||||||
strv_free(lines);
|
strv_free(lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_litest_test_param_fetch(const struct litest_test_parameters *params, ...)
|
||||||
|
{
|
||||||
|
struct litest_test_param *p;
|
||||||
|
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, params);
|
||||||
|
|
||||||
|
while ((name = va_arg(args, const char *))) {
|
||||||
|
bool found = false;
|
||||||
|
void **ptr = va_arg(args, void *);
|
||||||
|
list_for_each(p, ¶ms->test_params, link) {
|
||||||
|
if (streq(p->name, name)) {
|
||||||
|
found = true;
|
||||||
|
multivalue_extract(&p->value, ptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
litest_abort_msg("Unknown test parameter name '%s'", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct litest_test_parameters *
|
||||||
|
litest_test_parameters_new(void)
|
||||||
|
{
|
||||||
|
struct litest_test_parameters *params = zalloc(sizeof *params);
|
||||||
|
params->refcnt = 1;
|
||||||
|
list_init(¶ms->test_params);
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct litest_test_parameters *
|
||||||
|
litest_test_parameters_unref(struct litest_test_parameters *params)
|
||||||
|
{
|
||||||
|
if (params) {
|
||||||
|
assert(params->refcnt > 0);
|
||||||
|
if (--params->refcnt == 0) {
|
||||||
|
struct litest_test_param *p;
|
||||||
|
list_for_each_safe(p, ¶ms->test_params, link) {
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
free(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
litest_runner_log_test_result(struct litest_runner *runner, struct litest_runner_test *t)
|
litest_runner_log_test_result(struct litest_runner *runner, struct litest_runner_test *t)
|
||||||
{
|
{
|
||||||
|
|
@ -671,6 +726,16 @@ litest_runner_log_test_result(struct litest_runner *runner, struct litest_runner
|
||||||
if (range_is_valid(&t->desc.args.range))
|
if (range_is_valid(&t->desc.args.range))
|
||||||
fprintf(runner->fp, " rangeval: %d # %d..%d\n", t->desc.rangeval, min, max);
|
fprintf(runner->fp, " rangeval: %d # %d..%d\n", t->desc.rangeval, min, max);
|
||||||
|
|
||||||
|
if (t->desc.params) {
|
||||||
|
fprintf(runner->fp, " params:\n");
|
||||||
|
struct litest_test_param *p;
|
||||||
|
list_for_each(p, &t->desc.params->test_params, link) {
|
||||||
|
char *val = multivalue_as_str(&p->value);
|
||||||
|
fprintf(runner->fp, " %s: %s\n", p->name, val);
|
||||||
|
free(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(runner->fp,
|
fprintf(runner->fp,
|
||||||
" duration: %ld # (ms), total test run time: %02d:%02d\n",
|
" duration: %ld # (ms), total test run time: %02d:%02d\n",
|
||||||
t->times.end_millis - t->times.start_millis,
|
t->times.end_millis - t->times.start_millis,
|
||||||
|
|
|
||||||
|
|
@ -43,17 +43,47 @@ enum litest_runner_result {
|
||||||
LITEST_SYSTEM_ERROR = 80, /**< unrelated error occurred */
|
LITEST_SYSTEM_ERROR = 80, /**< unrelated error occurred */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* For parametrized tests (litest_add_parametrized and friends)
|
||||||
|
* a list of these is passed to every test. This struct isn't used
|
||||||
|
* directly, use litest_test_param_fetch() instead.
|
||||||
|
*/
|
||||||
|
struct litest_test_param {
|
||||||
|
struct list link;
|
||||||
|
char name[128];
|
||||||
|
struct multivalue value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct litest_test_parameters {
|
||||||
|
int refcnt;
|
||||||
|
struct list test_params;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct litest_test_parameters *
|
||||||
|
litest_test_parameters_new(void);
|
||||||
|
|
||||||
|
struct litest_test_parameters *
|
||||||
|
litest_test_parameters_unref(struct litest_test_parameters *params);
|
||||||
|
|
||||||
|
#define litest_test_param_fetch(...) \
|
||||||
|
_litest_test_param_fetch(__VA_ARGS__, NULL)
|
||||||
|
|
||||||
|
void
|
||||||
|
_litest_test_param_fetch(const struct litest_test_parameters *params, ...);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This struct is passed into every test.
|
* This struct is passed into every test.
|
||||||
*/
|
*/
|
||||||
struct litest_runner_test_env {
|
struct litest_runner_test_env {
|
||||||
int rangeval; /* The current value within the args.range (or 0) */
|
int rangeval; /* The current value within the args.range (or 0) */
|
||||||
|
const struct litest_test_parameters *params;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct litest_runner_test_description {
|
struct litest_runner_test_description {
|
||||||
char name[256]; /* The name of the test */
|
char name[512]; /* The name of the test */
|
||||||
int rangeval; /* The current value within the args.range (or 0) */
|
int rangeval; /* The current value within the args.range (or 0) */
|
||||||
|
|
||||||
|
struct litest_test_parameters *params;
|
||||||
|
|
||||||
/* test function and corresponding setup/teardown, if any */
|
/* test function and corresponding setup/teardown, if any */
|
||||||
enum litest_runner_result (*func)(const struct litest_runner_test_env *);
|
enum litest_runner_result (*func)(const struct litest_runner_test_env *);
|
||||||
void (*setup)(const struct litest_runner_test_description *);
|
void (*setup)(const struct litest_runner_test_description *);
|
||||||
|
|
|
||||||
|
|
@ -420,6 +420,82 @@ START_TEST(zalloc_too_large)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
struct permutation {
|
||||||
|
int32_t i;
|
||||||
|
const char *s;
|
||||||
|
bool b;
|
||||||
|
|
||||||
|
bool found;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
permutation_func(struct litest_parameters_permutation *permutation, void *userdata)
|
||||||
|
{
|
||||||
|
struct litest_parameters_permutation_value *value;
|
||||||
|
|
||||||
|
int32_t first;
|
||||||
|
const char *second;
|
||||||
|
bool third;
|
||||||
|
|
||||||
|
value = list_first_entry(&permutation->values, value, link);
|
||||||
|
multivalue_extract_typed(&value->value, 'i', &first);
|
||||||
|
|
||||||
|
value = list_first_entry(&value->link, value, link);
|
||||||
|
multivalue_extract_typed(&value->value, 's', &second);
|
||||||
|
|
||||||
|
value = list_first_entry(&value->link, value, link);
|
||||||
|
multivalue_extract_typed(&value->value, 'b', &third);
|
||||||
|
|
||||||
|
struct permutation *p = userdata;
|
||||||
|
while (p->s) {
|
||||||
|
if (p->i == first && streq(p->s, second) && p->b == third) {
|
||||||
|
p->found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(parameter_permutations)
|
||||||
|
{
|
||||||
|
struct permutation permutations[] = {
|
||||||
|
{ 1, "a", true },
|
||||||
|
{ 1, "a", false },
|
||||||
|
{ 1, "ab", true },
|
||||||
|
{ 1, "ab", false },
|
||||||
|
{ 1, "abc", true },
|
||||||
|
{ 1, "abc", false },
|
||||||
|
{ 2, "a", true },
|
||||||
|
{ 2, "a", false },
|
||||||
|
{ 2, "ab", true },
|
||||||
|
{ 2, "ab", false },
|
||||||
|
{ 2, "abc", true },
|
||||||
|
{ 2, "abc", false },
|
||||||
|
{ 3, "a", true },
|
||||||
|
{ 3, "a", false },
|
||||||
|
{ 3, "ab", true },
|
||||||
|
{ 3, "ab", false },
|
||||||
|
{ 3, "abc", true },
|
||||||
|
{ 3, "abc", false },
|
||||||
|
{ 0, NULL, false, false },
|
||||||
|
};
|
||||||
|
struct litest_parameters *params = litest_parameters_new("first", 'i', 3, 1, 2, 3,
|
||||||
|
"second", 's', 3, "a", "ab", "abc",
|
||||||
|
"third", 'b', 2, true, false,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
litest_parameters_permutations(params, permutation_func, permutations);
|
||||||
|
|
||||||
|
ARRAY_FOR_EACH(permutations, p) {
|
||||||
|
if (p->s == NULL)
|
||||||
|
break;
|
||||||
|
ck_assert_msg(p->found, "For %d/%s/%s", p->i, p->s, p->b ? "true" : "false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
litest_assert_macros_suite(void)
|
litest_assert_macros_suite(void)
|
||||||
{
|
{
|
||||||
|
|
@ -427,6 +503,7 @@ litest_assert_macros_suite(void)
|
||||||
Suite *s;
|
Suite *s;
|
||||||
|
|
||||||
s = suite_create("litest:assert macros");
|
s = suite_create("litest:assert macros");
|
||||||
|
#if 0
|
||||||
tc = tcase_create("assert");
|
tc = tcase_create("assert");
|
||||||
tcase_add_test_raise_signal(tc, litest_assert_trigger, SIGABRT);
|
tcase_add_test_raise_signal(tc, litest_assert_trigger, SIGABRT);
|
||||||
tcase_add_test(tc, litest_assert_notrigger);
|
tcase_add_test(tc, litest_assert_notrigger);
|
||||||
|
|
@ -498,6 +575,11 @@ litest_assert_macros_suite(void)
|
||||||
tcase_add_test_raise_signal(tc, zalloc_too_large, SIGABRT);
|
tcase_add_test_raise_signal(tc, zalloc_too_large, SIGABRT);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
tc = tcase_create("parameters ");
|
||||||
|
tcase_add_test(tc, parameter_permutations);
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
616
test/litest.c
616
test/litest.c
|
|
@ -88,6 +88,14 @@ static const char *filter_test = NULL;
|
||||||
static const char *filter_device = NULL;
|
static const char *filter_device = NULL;
|
||||||
static const char *filter_group = NULL;
|
static const char *filter_group = NULL;
|
||||||
static int filter_rangeval = INT_MIN;
|
static int filter_rangeval = INT_MIN;
|
||||||
|
|
||||||
|
struct param_filter {
|
||||||
|
char name[64];
|
||||||
|
char glob[64];
|
||||||
|
};
|
||||||
|
struct param_filter filter_params[8]; /* name=NULL terminated */
|
||||||
|
|
||||||
|
|
||||||
static struct quirks_context *quirks_context;
|
static struct quirks_context *quirks_context;
|
||||||
|
|
||||||
struct created_file {
|
struct created_file {
|
||||||
|
|
@ -266,6 +274,8 @@ struct test {
|
||||||
struct range range;
|
struct range range;
|
||||||
int rangeval;
|
int rangeval;
|
||||||
bool deviceless;
|
bool deviceless;
|
||||||
|
|
||||||
|
struct litest_test_parameters *params;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct suite {
|
struct suite {
|
||||||
|
|
@ -274,6 +284,316 @@ struct suite {
|
||||||
char *name;
|
char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct litest_parameter_value {
|
||||||
|
size_t refcnt;
|
||||||
|
struct list link; /* litest_parameter->values */
|
||||||
|
|
||||||
|
struct multivalue value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct litest_parameter {
|
||||||
|
size_t refcnt;
|
||||||
|
struct list link; /* litest_parameters.params */
|
||||||
|
char name[128];
|
||||||
|
char type; /* One of u, i, d, c, s, b */
|
||||||
|
|
||||||
|
struct list values; /* litest_parameter_value */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct litest_parameters {
|
||||||
|
size_t refcnt;
|
||||||
|
struct list params; /* struct litest_parameter */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct litest_parameter_value *
|
||||||
|
litest_parameter_value_new(void)
|
||||||
|
{
|
||||||
|
struct litest_parameter_value *pv = zalloc(sizeof *pv);
|
||||||
|
|
||||||
|
list_init(&pv->link);
|
||||||
|
pv->refcnt = 1;
|
||||||
|
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
litest_parameter_add_string(struct litest_parameter *p, const char *s)
|
||||||
|
{
|
||||||
|
assert(p->type == 's');
|
||||||
|
|
||||||
|
struct litest_parameter_value *pv = litest_parameter_value_new();
|
||||||
|
pv->value = multivalue_new_string(s);
|
||||||
|
list_append(&p->values, &pv->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
litest_parameter_add_char(struct litest_parameter *p, char c)
|
||||||
|
{
|
||||||
|
assert(p->type == 'c');
|
||||||
|
|
||||||
|
struct litest_parameter_value *pv = litest_parameter_value_new();
|
||||||
|
pv->value = multivalue_new_char(c);
|
||||||
|
list_append(&p->values, &pv->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
litest_parameter_add_bool(struct litest_parameter *p, bool b)
|
||||||
|
{
|
||||||
|
assert(p->type == 'b');
|
||||||
|
|
||||||
|
struct litest_parameter_value *pv = litest_parameter_value_new();
|
||||||
|
pv->value = multivalue_new_bool(b);
|
||||||
|
list_append(&p->values, &pv->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
litest_parameter_add_u32(struct litest_parameter *p, uint32_t u)
|
||||||
|
{
|
||||||
|
assert(p->type == 'u');
|
||||||
|
|
||||||
|
struct litest_parameter_value *pv = litest_parameter_value_new();
|
||||||
|
pv->value = multivalue_new_u32(u);
|
||||||
|
list_append(&p->values, &pv->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
litest_parameter_add_i32(struct litest_parameter *p, int32_t i)
|
||||||
|
{
|
||||||
|
assert(p->type == 'i');
|
||||||
|
|
||||||
|
struct litest_parameter_value *pv = litest_parameter_value_new();
|
||||||
|
pv->value = multivalue_new_i32(i);
|
||||||
|
list_append(&p->values, &pv->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
litest_parameter_add_double(struct litest_parameter *p, double d)
|
||||||
|
{
|
||||||
|
assert(p->type == 'd');
|
||||||
|
|
||||||
|
struct litest_parameter_value *pv = litest_parameter_value_new();
|
||||||
|
pv->value = multivalue_new_double(d);
|
||||||
|
list_append(&p->values, &pv->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static struct litest_parameter_value *
|
||||||
|
litest_parameter_value_ref(struct litest_parameter_value *pv) {
|
||||||
|
assert(pv);
|
||||||
|
assert(pv->refcnt > 0);
|
||||||
|
pv->refcnt++;
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct litest_parameter_value *
|
||||||
|
litest_parameter_value_unref(struct litest_parameter_value *pv) {
|
||||||
|
if (pv) {
|
||||||
|
assert(pv->refcnt > 0);
|
||||||
|
if (--pv->refcnt == 0) {
|
||||||
|
list_remove(&pv->link);
|
||||||
|
free(pv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct litest_parameter*
|
||||||
|
litest_parameter_new(const char *name, char type)
|
||||||
|
{
|
||||||
|
struct litest_parameter *p = zalloc(sizeof *p);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'b':
|
||||||
|
case 'c':
|
||||||
|
case 'd':
|
||||||
|
case 'i':
|
||||||
|
case 's':
|
||||||
|
case 'u':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(!"Type not yet implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
list_init(&p->link);
|
||||||
|
list_init(&p->values);
|
||||||
|
snprintf(p->name, sizeof(p->name), "%s", name);
|
||||||
|
p->type = type;
|
||||||
|
p->refcnt = 1;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct litest_parameter *
|
||||||
|
litest_parameter_ref(struct litest_parameter *p) {
|
||||||
|
assert(p);
|
||||||
|
assert(p->refcnt > 0);
|
||||||
|
p->refcnt++;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct litest_parameter *
|
||||||
|
litest_parameter_unref(struct litest_parameter *p) {
|
||||||
|
if (p) {
|
||||||
|
assert(p->refcnt > 0);
|
||||||
|
if (--p->refcnt == 0) {
|
||||||
|
struct litest_parameter_value *pv;
|
||||||
|
list_for_each_safe(pv, &p->values, link) {
|
||||||
|
litest_parameter_value_unref(pv);
|
||||||
|
}
|
||||||
|
list_remove(&p->link);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
litest_parameters_add(struct litest_parameters *ps, struct litest_parameter *param)
|
||||||
|
{
|
||||||
|
struct litest_parameter *p;
|
||||||
|
list_for_each(p, &ps->params, link) {
|
||||||
|
assert(!streq(p->name, param->name));
|
||||||
|
}
|
||||||
|
|
||||||
|
litest_parameter_ref(param);
|
||||||
|
list_append(&ps->params, ¶m->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct litest_parameters *
|
||||||
|
_litest_parameters_new(const char *name, ...) {
|
||||||
|
struct litest_parameters *ps = zalloc(sizeof *ps);
|
||||||
|
|
||||||
|
list_init(&ps->params);
|
||||||
|
ps->refcnt = 1;
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, name);
|
||||||
|
|
||||||
|
while (name) {
|
||||||
|
char type = va_arg(args, int);
|
||||||
|
unsigned int nargs = va_arg(args, unsigned int);
|
||||||
|
|
||||||
|
struct litest_parameter *param = litest_parameter_new(name, type);
|
||||||
|
for (unsigned int _ = 0; _ < nargs; _++) {
|
||||||
|
switch (type) {
|
||||||
|
case 'b': {
|
||||||
|
bool b = va_arg(args, int);
|
||||||
|
litest_parameter_add_bool(param, b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'c': {
|
||||||
|
char b = va_arg(args, int);
|
||||||
|
litest_parameter_add_char(param, b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u': {
|
||||||
|
uint32_t b = va_arg(args, uint32_t);
|
||||||
|
litest_parameter_add_u32(param, b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'i': {
|
||||||
|
int32_t b = va_arg(args, int32_t);
|
||||||
|
litest_parameter_add_i32(param, b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd': {
|
||||||
|
double b = va_arg(args, double);
|
||||||
|
litest_parameter_add_double(param, b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's': {
|
||||||
|
const char *s = va_arg(args, const char *);
|
||||||
|
litest_parameter_add_string(param, s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
litest_parameters_add(ps, param);
|
||||||
|
litest_parameter_unref(param);
|
||||||
|
name = va_arg(args, const char *);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
return ps;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct litest_parameters *
|
||||||
|
litest_parameters_ref(struct litest_parameters *p) {
|
||||||
|
assert(p);
|
||||||
|
assert(p->refcnt > 0);
|
||||||
|
p->refcnt++;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct litest_parameters *
|
||||||
|
litest_parameters_unref(struct litest_parameters *params) {
|
||||||
|
if (params) {
|
||||||
|
assert(params->refcnt > 0);
|
||||||
|
if (--params->refcnt == 0) {
|
||||||
|
struct litest_parameter *p;
|
||||||
|
list_for_each_safe(p, ¶ms->params, link) {
|
||||||
|
litest_parameter_unref(p);
|
||||||
|
}
|
||||||
|
free(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
_permutate(struct litest_parameters_permutation *permutation,
|
||||||
|
struct list *next_param,
|
||||||
|
void *list_head,
|
||||||
|
litest_parameters_permutation_func_t func,
|
||||||
|
void *userdata)
|
||||||
|
{
|
||||||
|
if (next_param->next == list_head) {
|
||||||
|
func(permutation, userdata);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
struct litest_parameter_value *pv;
|
||||||
|
struct litest_parameter *param = list_first_entry(next_param, param, link);
|
||||||
|
list_for_each(pv, ¶m->values, link) {
|
||||||
|
struct litest_parameters_permutation_value v = {
|
||||||
|
.value = pv->value,
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(v.name, param->name, min(sizeof(v.name), sizeof(param->name)));
|
||||||
|
|
||||||
|
list_append(&permutation->values, &v.link);
|
||||||
|
int rc = _permutate(permutation, ¶m->link, list_head, func, userdata);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
list_remove(&v.link);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the given function func with each permutation of
|
||||||
|
* the given test parameters.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
litest_parameters_permutations(struct litest_parameters *params,
|
||||||
|
litest_parameters_permutation_func_t func,
|
||||||
|
void *userdata)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct litest_parameters_permutation permutation;
|
||||||
|
list_init(&permutation.values);
|
||||||
|
|
||||||
|
return _permutate(&permutation, ¶ms->params, ¶ms->params, func, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
static struct litest_device *current_device;
|
static struct litest_device *current_device;
|
||||||
|
|
||||||
struct litest_device *litest_current_device(void)
|
struct litest_device *litest_current_device(void)
|
||||||
|
|
@ -432,6 +752,94 @@ litest_add_tcase_for_device(struct suite *suite,
|
||||||
} while (++rangeval < range->upper);
|
} while (++rangeval < range->upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct permutation_userdata
|
||||||
|
{
|
||||||
|
struct suite *suite;
|
||||||
|
const char *funcname;
|
||||||
|
const void *func;
|
||||||
|
const struct litest_test_device *dev;
|
||||||
|
char devname[64]; /* set if dev == NULL */
|
||||||
|
|
||||||
|
const struct param_filter *param_filters; /* name=NULL terminated */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
permutation_func(struct litest_parameters_permutation *permutation, void *userdata)
|
||||||
|
{
|
||||||
|
struct permutation_userdata *data = userdata;
|
||||||
|
|
||||||
|
struct litest_test_parameters *params = litest_test_parameters_new();
|
||||||
|
struct litest_parameters_permutation_value *pmv;
|
||||||
|
bool all_filtered = true;
|
||||||
|
list_for_each(pmv, &permutation->values, link) {
|
||||||
|
const struct param_filter *f = data->param_filters;
|
||||||
|
bool filtered = false;
|
||||||
|
while (!filtered && strlen(f->name)) {
|
||||||
|
if (streq(pmv->name, f->name)) {
|
||||||
|
char *s = multivalue_as_str(&pmv->value);
|
||||||
|
if (fnmatch(f->glob, s, 0) != 0)
|
||||||
|
filtered = true;
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
f++;
|
||||||
|
}
|
||||||
|
if (!filtered) {
|
||||||
|
struct litest_test_param *tp = zalloc(sizeof *tp);
|
||||||
|
snprintf(tp->name, sizeof(tp->name), "%s", pmv->name);
|
||||||
|
tp->value = multivalue_copy(&pmv->value);
|
||||||
|
list_append(¶ms->test_params, &tp->link);
|
||||||
|
|
||||||
|
all_filtered = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (all_filtered)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct test *t;
|
||||||
|
|
||||||
|
t = zalloc(sizeof(*t));
|
||||||
|
t->name = safe_strdup(data->funcname);
|
||||||
|
t->func = data->func;
|
||||||
|
if (data->dev) {
|
||||||
|
t->devname = safe_strdup(data->dev->shortname);
|
||||||
|
t->setup = data->dev->setup;
|
||||||
|
t->teardown = data->dev->teardown ?
|
||||||
|
data->dev->teardown : litest_generic_device_teardown;
|
||||||
|
} else {
|
||||||
|
t->devname = safe_strdup(data->devname);
|
||||||
|
t->setup = NULL;
|
||||||
|
t->teardown = NULL;
|
||||||
|
}
|
||||||
|
t->rangeval = 0;
|
||||||
|
t->params = params;
|
||||||
|
|
||||||
|
list_append(&data->suite->tests, &t->node);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
litest_add_tcase_for_device_with_params(struct suite *suite,
|
||||||
|
const char *funcname,
|
||||||
|
const void *func,
|
||||||
|
const struct litest_test_device *dev,
|
||||||
|
struct litest_parameters *params)
|
||||||
|
{
|
||||||
|
if (run_deviceless)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct permutation_userdata data = {
|
||||||
|
.suite = suite,
|
||||||
|
.funcname = funcname,
|
||||||
|
.func = func,
|
||||||
|
.dev = dev,
|
||||||
|
.param_filters = filter_params,
|
||||||
|
};
|
||||||
|
|
||||||
|
litest_parameters_permutations(params, permutation_func, &data);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
litest_add_tcase_no_device(struct suite *suite,
|
litest_add_tcase_no_device(struct suite *suite,
|
||||||
const void *func,
|
const void *func,
|
||||||
|
|
@ -471,6 +879,32 @@ litest_add_tcase_no_device(struct suite *suite,
|
||||||
} while (++rangeval < range->upper);
|
} while (++rangeval < range->upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
litest_add_tcase_no_device_with_params(struct suite *suite,
|
||||||
|
const void *func,
|
||||||
|
const char *funcname,
|
||||||
|
struct litest_parameters *params)
|
||||||
|
{
|
||||||
|
const char *test_name = funcname;
|
||||||
|
|
||||||
|
if (filter_device &&
|
||||||
|
fnmatch(filter_device, test_name, 0) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (run_deviceless)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct permutation_userdata data = {
|
||||||
|
.suite = suite,
|
||||||
|
.funcname = funcname,
|
||||||
|
.func = func,
|
||||||
|
.param_filters = filter_params,
|
||||||
|
};
|
||||||
|
snprintf(data.devname, sizeof(data.devname), "no device");
|
||||||
|
|
||||||
|
litest_parameters_permutations(params, permutation_func, &data);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
litest_add_tcase_deviceless(struct suite *suite,
|
litest_add_tcase_deviceless(struct suite *suite,
|
||||||
const void *func,
|
const void *func,
|
||||||
|
|
@ -508,13 +942,37 @@ litest_add_tcase_deviceless(struct suite *suite,
|
||||||
} while (++rangeval < range->upper);
|
} while (++rangeval < range->upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
litest_add_tcase_deviceless_with_params(struct suite *suite,
|
||||||
|
const void *func,
|
||||||
|
const char *funcname,
|
||||||
|
struct litest_parameters *params)
|
||||||
|
{
|
||||||
|
const char *test_name = funcname;
|
||||||
|
|
||||||
|
if (filter_device &&
|
||||||
|
fnmatch(filter_device, test_name, 0) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct permutation_userdata data = {
|
||||||
|
.suite = suite,
|
||||||
|
.funcname = funcname,
|
||||||
|
.func = func,
|
||||||
|
.param_filters = filter_params,
|
||||||
|
};
|
||||||
|
snprintf(data.devname, sizeof(data.devname), "deviceless");
|
||||||
|
|
||||||
|
litest_parameters_permutations(params, permutation_func, &data);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
litest_add_tcase(const char *filename,
|
litest_add_tcase(const char *filename,
|
||||||
const char *funcname,
|
const char *funcname,
|
||||||
const void *func,
|
const void *func,
|
||||||
int64_t required,
|
int64_t required,
|
||||||
int64_t excluded,
|
int64_t excluded,
|
||||||
const struct range *range)
|
const struct range *range,
|
||||||
|
struct litest_parameters *params)
|
||||||
{
|
{
|
||||||
bool added = false;
|
bool added = false;
|
||||||
|
|
||||||
|
|
@ -532,10 +990,16 @@ litest_add_tcase(const char *filename,
|
||||||
|
|
||||||
if (required == LITEST_DEVICELESS &&
|
if (required == LITEST_DEVICELESS &&
|
||||||
excluded == LITEST_DEVICELESS) {
|
excluded == LITEST_DEVICELESS) {
|
||||||
|
if (params)
|
||||||
|
litest_add_tcase_deviceless_with_params(suite, func, funcname, params);
|
||||||
|
else
|
||||||
litest_add_tcase_deviceless(suite, func, funcname, range);
|
litest_add_tcase_deviceless(suite, func, funcname, range);
|
||||||
added = true;
|
added = true;
|
||||||
} else if (required == LITEST_DISABLE_DEVICE &&
|
} else if (required == LITEST_DISABLE_DEVICE &&
|
||||||
excluded == LITEST_DISABLE_DEVICE) {
|
excluded == LITEST_DISABLE_DEVICE) {
|
||||||
|
if (params)
|
||||||
|
litest_add_tcase_no_device_with_params(suite, func, funcname, params);
|
||||||
|
else
|
||||||
litest_add_tcase_no_device(suite, func, funcname, range);
|
litest_add_tcase_no_device(suite, func, funcname, range);
|
||||||
added = true;
|
added = true;
|
||||||
} else if (required != LITEST_ANY || excluded != LITEST_ANY) {
|
} else if (required != LITEST_ANY || excluded != LITEST_ANY) {
|
||||||
|
|
@ -552,11 +1016,19 @@ litest_add_tcase(const char *filename,
|
||||||
(dev->features & excluded) != 0)
|
(dev->features & excluded) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (params) {
|
||||||
|
litest_add_tcase_for_device_with_params(suite,
|
||||||
|
funcname,
|
||||||
|
func,
|
||||||
|
dev,
|
||||||
|
params);
|
||||||
|
} else {
|
||||||
litest_add_tcase_for_device(suite,
|
litest_add_tcase_for_device(suite,
|
||||||
funcname,
|
funcname,
|
||||||
func,
|
func,
|
||||||
dev,
|
dev,
|
||||||
range);
|
range);
|
||||||
|
}
|
||||||
added = true;
|
added = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -570,11 +1042,19 @@ litest_add_tcase(const char *filename,
|
||||||
fnmatch(filter_device, dev->shortname, 0) != 0)
|
fnmatch(filter_device, dev->shortname, 0) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (params) {
|
||||||
|
litest_add_tcase_for_device_with_params(suite,
|
||||||
|
funcname,
|
||||||
|
func,
|
||||||
|
dev,
|
||||||
|
params);
|
||||||
|
} else {
|
||||||
litest_add_tcase_for_device(suite,
|
litest_add_tcase_for_device(suite,
|
||||||
funcname,
|
funcname,
|
||||||
func,
|
func,
|
||||||
dev,
|
dev,
|
||||||
range);
|
range);
|
||||||
|
}
|
||||||
added = true;
|
added = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -594,6 +1074,18 @@ _litest_add_no_device(const char *name, const char *funcname, const void *func)
|
||||||
_litest_add(name, funcname, func, LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE);
|
_litest_add(name, funcname, func, LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_litest_add_parametrized_no_device(const char *name,
|
||||||
|
const char *funcname,
|
||||||
|
const void *func,
|
||||||
|
struct litest_parameters *params)
|
||||||
|
{
|
||||||
|
_litest_add_parametrized(name, funcname, func,
|
||||||
|
LITEST_DISABLE_DEVICE,
|
||||||
|
LITEST_DISABLE_DEVICE,
|
||||||
|
params);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_litest_add_ranged_no_device(const char *name,
|
_litest_add_ranged_no_device(const char *name,
|
||||||
const char *funcname,
|
const char *funcname,
|
||||||
|
|
@ -621,6 +1113,18 @@ _litest_add_deviceless(const char *name,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_litest_add_parametrized_deviceless(const char *name,
|
||||||
|
const char *funcname,
|
||||||
|
const void *func,
|
||||||
|
struct litest_parameters *params)
|
||||||
|
{
|
||||||
|
_litest_add_parametrized(name, funcname, func,
|
||||||
|
LITEST_DISABLE_DEVICE,
|
||||||
|
LITEST_DISABLE_DEVICE,
|
||||||
|
params);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_litest_add(const char *name,
|
_litest_add(const char *name,
|
||||||
const char *funcname,
|
const char *funcname,
|
||||||
|
|
@ -644,7 +1148,19 @@ _litest_add_ranged(const char *name,
|
||||||
int64_t excluded,
|
int64_t excluded,
|
||||||
const struct range *range)
|
const struct range *range)
|
||||||
{
|
{
|
||||||
litest_add_tcase(name, funcname, func, required, excluded, range);
|
litest_add_tcase(name, funcname, func, required, excluded, range, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_litest_add_parametrized(const char *name,
|
||||||
|
const char *funcname,
|
||||||
|
const void *func,
|
||||||
|
int64_t required,
|
||||||
|
int64_t excluded,
|
||||||
|
struct litest_parameters *params)
|
||||||
|
{
|
||||||
|
litest_add_tcase(name, funcname, func, required, excluded, NULL, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -699,6 +1215,50 @@ _litest_add_ranged_for_device(const char *filename,
|
||||||
litest_abort_msg("Invalid test device type");
|
litest_abort_msg("Invalid test device type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_litest_add_parametrized_for_device(const char *filename,
|
||||||
|
const char *funcname,
|
||||||
|
const void *func,
|
||||||
|
enum litest_device_type type,
|
||||||
|
struct litest_parameters *params)
|
||||||
|
{
|
||||||
|
struct litest_test_device *dev;
|
||||||
|
bool device_filtered = false;
|
||||||
|
|
||||||
|
litest_assert(type < LITEST_NO_DEVICE);
|
||||||
|
|
||||||
|
if (filter_test &&
|
||||||
|
fnmatch(filter_test, funcname, 0) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct suite *s = current_suite;
|
||||||
|
|
||||||
|
if (filter_group && fnmatch(filter_group, s->name, 0) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
list_for_each(dev, &devices, node) {
|
||||||
|
if (filter_device &&
|
||||||
|
fnmatch(filter_device, dev->shortname, 0) != 0) {
|
||||||
|
device_filtered = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->type == type) {
|
||||||
|
litest_add_tcase_for_device_with_params(s,
|
||||||
|
funcname,
|
||||||
|
func,
|
||||||
|
dev,
|
||||||
|
params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only abort if no filter was set, that's a bug */
|
||||||
|
if (!device_filtered)
|
||||||
|
litest_abort_msg("Invalid test device type");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
|
LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
|
||||||
static void
|
static void
|
||||||
litest_log_handler(struct libinput *libinput,
|
litest_log_handler(struct libinput *libinput,
|
||||||
|
|
@ -954,7 +1514,7 @@ litest_run_suite(struct list *suites, int njobs)
|
||||||
list_for_each(s, suites, node) {
|
list_for_each(s, suites, node) {
|
||||||
struct test *t;
|
struct test *t;
|
||||||
list_for_each(t, &s->tests, node) {
|
list_for_each(t, &s->tests, node) {
|
||||||
struct litest_runner_test_description tdesc;
|
struct litest_runner_test_description tdesc = {0};
|
||||||
|
|
||||||
if (range_is_valid(&t->range)) {
|
if (range_is_valid(&t->range)) {
|
||||||
snprintf(tdesc.name, sizeof(tdesc.name),
|
snprintf(tdesc.name, sizeof(tdesc.name),
|
||||||
|
|
@ -963,6 +1523,24 @@ litest_run_suite(struct list *suites, int njobs)
|
||||||
t->name,
|
t->name,
|
||||||
t->devname,
|
t->devname,
|
||||||
t->rangeval);
|
t->rangeval);
|
||||||
|
} else if (t->params) {
|
||||||
|
char buf[256] = {0};
|
||||||
|
|
||||||
|
struct litest_test_param *tp;
|
||||||
|
bool is_first = true;
|
||||||
|
list_for_each(tp, &t->params->test_params, link) {
|
||||||
|
char *val = multivalue_as_str(&tp->value);
|
||||||
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
||||||
|
"%s%s:%s", is_first ? "" : ",", tp->name, val);
|
||||||
|
free(val);
|
||||||
|
is_first = false;
|
||||||
|
}
|
||||||
|
snprintf(tdesc.name, sizeof(tdesc.name),
|
||||||
|
"%s:%s:%s:%s",
|
||||||
|
s->name,
|
||||||
|
t->name,
|
||||||
|
t->devname,
|
||||||
|
buf);
|
||||||
} else {
|
} else {
|
||||||
snprintf(tdesc.name, sizeof(tdesc.name),
|
snprintf(tdesc.name, sizeof(tdesc.name),
|
||||||
"%s:%s:%s",
|
"%s:%s:%s",
|
||||||
|
|
@ -975,6 +1553,7 @@ litest_run_suite(struct list *suites, int njobs)
|
||||||
tdesc.teardown = t->teardown;
|
tdesc.teardown = t->teardown;
|
||||||
tdesc.args.range = t->range;
|
tdesc.args.range = t->range;
|
||||||
tdesc.rangeval = t->rangeval;
|
tdesc.rangeval = t->rangeval;
|
||||||
|
tdesc.params = t->params;
|
||||||
litest_runner_add_test(runner, &tdesc);
|
litest_runner_add_test(runner, &tdesc);
|
||||||
ntests++;
|
ntests++;
|
||||||
}
|
}
|
||||||
|
|
@ -4523,6 +5102,7 @@ litest_parse_argv(int argc, char **argv)
|
||||||
OPT_FILTER_GROUP,
|
OPT_FILTER_GROUP,
|
||||||
OPT_FILTER_RANGEVAL,
|
OPT_FILTER_RANGEVAL,
|
||||||
OPT_FILTER_DEVICELESS,
|
OPT_FILTER_DEVICELESS,
|
||||||
|
OPT_FILTER_PARAMETER,
|
||||||
OPT_OUTPUT_FILE,
|
OPT_OUTPUT_FILE,
|
||||||
OPT_JOBS,
|
OPT_JOBS,
|
||||||
OPT_LIST,
|
OPT_LIST,
|
||||||
|
|
@ -4534,6 +5114,7 @@ litest_parse_argv(int argc, char **argv)
|
||||||
{ "filter-group", 1, 0, OPT_FILTER_GROUP },
|
{ "filter-group", 1, 0, OPT_FILTER_GROUP },
|
||||||
{ "filter-rangeval", 1, 0, OPT_FILTER_RANGEVAL },
|
{ "filter-rangeval", 1, 0, OPT_FILTER_RANGEVAL },
|
||||||
{ "filter-deviceless", 0, 0, OPT_FILTER_DEVICELESS },
|
{ "filter-deviceless", 0, 0, OPT_FILTER_DEVICELESS },
|
||||||
|
{ "filter-parameter", 1, 0, OPT_FILTER_PARAMETER },
|
||||||
{ "output-file", 1, 0, OPT_OUTPUT_FILE },
|
{ "output-file", 1, 0, OPT_OUTPUT_FILE },
|
||||||
{ "exitfirst", 0, 0, OPT_EXIT_FIRST },
|
{ "exitfirst", 0, 0, OPT_EXIT_FIRST },
|
||||||
{ "jobs", 1, 0, OPT_JOBS },
|
{ "jobs", 1, 0, OPT_JOBS },
|
||||||
|
|
@ -4592,6 +5173,9 @@ litest_parse_argv(int argc, char **argv)
|
||||||
" Only run tests with the given range value\n"
|
" Only run tests with the given range value\n"
|
||||||
" --filter-deviceless=.... \n"
|
" --filter-deviceless=.... \n"
|
||||||
" Glob to filter on tests that do not create test devices\n"
|
" Glob to filter on tests that do not create test devices\n"
|
||||||
|
" --filter-parameter=param1:glob,param2:glob,... \n"
|
||||||
|
" Glob(s) to filter on the given parameters in their string representation.\n"
|
||||||
|
" Boolean parameters are filtered via 'true' and 'false'.\n"
|
||||||
" --verbose\n"
|
" --verbose\n"
|
||||||
" Enable verbose output\n"
|
" Enable verbose output\n"
|
||||||
" --jobs 8\n"
|
" --jobs 8\n"
|
||||||
|
|
@ -4623,6 +5207,31 @@ litest_parse_argv(int argc, char **argv)
|
||||||
case OPT_FILTER_RANGEVAL:
|
case OPT_FILTER_RANGEVAL:
|
||||||
filter_rangeval = atoi(optarg);
|
filter_rangeval = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
case OPT_FILTER_PARAMETER: {
|
||||||
|
size_t nelems;
|
||||||
|
char **params = strv_from_string(optarg, ",", &nelems);
|
||||||
|
const size_t max_filters = ARRAY_LENGTH(filter_params) - 1;
|
||||||
|
if (nelems >= max_filters) {
|
||||||
|
fprintf(stderr, "Only %zd parameter filters are supported\n", max_filters);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < nelems; i++) {
|
||||||
|
size_t n;
|
||||||
|
char **strv = strv_from_string(params[i], ":", &n);
|
||||||
|
assert(n == 2);
|
||||||
|
|
||||||
|
const char *name = strv[0];
|
||||||
|
const char *glob = strv[1];
|
||||||
|
|
||||||
|
struct param_filter *f = &filter_params[i];
|
||||||
|
snprintf(f->name, sizeof(f->name), "%s", name);
|
||||||
|
snprintf(f->glob, sizeof(f->glob), "%s", glob);
|
||||||
|
|
||||||
|
strv_free(strv);
|
||||||
|
}
|
||||||
|
strv_free(params);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'j':
|
case 'j':
|
||||||
case OPT_JOBS:
|
case OPT_JOBS:
|
||||||
jobs = atoi(optarg);
|
jobs = atoi(optarg);
|
||||||
|
|
@ -4776,6 +5385,7 @@ litest_free_test_list(struct list *tests)
|
||||||
struct test *t;
|
struct test *t;
|
||||||
|
|
||||||
list_for_each_safe(t, &s->tests, node) {
|
list_for_each_safe(t, &s->tests, node) {
|
||||||
|
litest_test_parameters_unref(t->params);
|
||||||
free(t->name);
|
free(t->name);
|
||||||
free(t->devname);
|
free(t->devname);
|
||||||
list_remove(&t->node);
|
list_remove(&t->node);
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@
|
||||||
#include "litest-runner.h"
|
#include "litest-runner.h"
|
||||||
|
|
||||||
#define START_TEST(func_) \
|
#define START_TEST(func_) \
|
||||||
static enum litest_runner_result func_(const struct litest_runner_test_env *test_env_) { \
|
static enum litest_runner_result func_(const struct litest_runner_test_env *test_env) { \
|
||||||
int _i __attribute__((unused)) = test_env_->rangeval;
|
int _i __attribute__((unused)) = test_env->rangeval;
|
||||||
|
|
||||||
#define END_TEST \
|
#define END_TEST \
|
||||||
return LITEST_PASS; \
|
return LITEST_PASS; \
|
||||||
|
|
@ -589,20 +589,87 @@ void litest_disable_log_handler(struct libinput *libinput);
|
||||||
void litest_restore_log_handler(struct libinput *libinput);
|
void litest_restore_log_handler(struct libinput *libinput);
|
||||||
void litest_set_log_handler_bug(struct libinput *libinput);
|
void litest_set_log_handler_bug(struct libinput *libinput);
|
||||||
|
|
||||||
|
struct litest_parameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new set of parameters for a test case.
|
||||||
|
*
|
||||||
|
* This function takes a variable set of arguments in the format
|
||||||
|
* [name, type, count, arg1, arg2, arg3, ..], for example:
|
||||||
|
*
|
||||||
|
* litest_parameter_new("axis", 'u', 2, ABS_X, ABS_Y,
|
||||||
|
* "direction", 's', 4, "north", "south", "east", "west",
|
||||||
|
* NULL);
|
||||||
|
*
|
||||||
|
* Parsing stops at the first null name argument.
|
||||||
|
*/
|
||||||
|
struct litest_parameters *
|
||||||
|
_litest_parameters_new(const char *name, ...);
|
||||||
|
|
||||||
|
/* Helper to ensure it's always null-terminated */
|
||||||
|
#define litest_parameters_new(name_, ...) \
|
||||||
|
_litest_parameters_new(name_, __VA_ARGS__, NULL)
|
||||||
|
|
||||||
|
struct litest_parameters_permutation_value {
|
||||||
|
struct list link;
|
||||||
|
char name[128];
|
||||||
|
const struct multivalue value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Argument for the callback function to litest_parameters_permutations().
|
||||||
|
* This is simple wrapper around a linked list that contains all elements
|
||||||
|
* of the current permutation.
|
||||||
|
*/
|
||||||
|
struct litest_parameters_permutation {
|
||||||
|
struct list values; /* struct litest_parameters_permutation_value */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function invoked for each permutation of a struct litest_parameters.
|
||||||
|
*/
|
||||||
|
typedef int (*litest_parameters_permutation_func_t)(struct litest_parameters_permutation *permutation, void *userdata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permutates the given parameters and calls func for every possible
|
||||||
|
* permutation. If func returns a nonzero status, permutation stops
|
||||||
|
* and that nonzero status is returned to the caller.
|
||||||
|
*
|
||||||
|
* Userdata is passed through as-is.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
litest_parameters_permutations(struct litest_parameters *params,
|
||||||
|
litest_parameters_permutation_func_t func,
|
||||||
|
void *userdata);
|
||||||
|
|
||||||
|
struct litest_parameters *
|
||||||
|
litest_parameters_ref(struct litest_parameters *p);
|
||||||
|
|
||||||
|
struct litest_parameters *
|
||||||
|
litest_parameters_unref(struct litest_parameters *params);
|
||||||
|
|
||||||
#define litest_add(func_, ...) \
|
#define litest_add(func_, ...) \
|
||||||
_litest_add(__FILE__, #func_, func_, __VA_ARGS__)
|
_litest_add(__FILE__, #func_, func_, __VA_ARGS__)
|
||||||
#define litest_add_ranged(func_, ...) \
|
#define litest_add_ranged(func_, ...) \
|
||||||
_litest_add_ranged(__FILE__, #func_, func_, __VA_ARGS__)
|
_litest_add_ranged(__FILE__, #func_, func_, __VA_ARGS__)
|
||||||
|
#define litest_add_parametrized(func_, ...) \
|
||||||
|
_litest_add_parametrized(__FILE__, #func_, func_, __VA_ARGS__)
|
||||||
#define litest_add_for_device(func_, ...) \
|
#define litest_add_for_device(func_, ...) \
|
||||||
_litest_add_for_device(__FILE__, #func_, func_, __VA_ARGS__)
|
_litest_add_for_device(__FILE__, #func_, func_, __VA_ARGS__)
|
||||||
#define litest_add_ranged_for_device(func_, ...) \
|
#define litest_add_ranged_for_device(func_, ...) \
|
||||||
_litest_add_ranged_for_device(__FILE__, #func_, func_, __VA_ARGS__)
|
_litest_add_ranged_for_device(__FILE__, #func_, func_, __VA_ARGS__)
|
||||||
|
#define litest_add_parametrized_for_device(func_, ...) \
|
||||||
|
_litest_add_parametrized_for_device(__FILE__, #func_, func_, __VA_ARGS__)
|
||||||
#define litest_add_no_device(func_) \
|
#define litest_add_no_device(func_) \
|
||||||
_litest_add_no_device(__FILE__, #func_, func_)
|
_litest_add_no_device(__FILE__, #func_, func_)
|
||||||
|
#define litest_add_parametrized_no_device(func_, ...) \
|
||||||
|
_litest_add_parametrized_no_device(__FILE__, #func_, func_, __VA_ARGS__)
|
||||||
#define litest_add_ranged_no_device(func_, ...) \
|
#define litest_add_ranged_no_device(func_, ...) \
|
||||||
_litest_add_ranged_no_device(__FILE__, #func_, func_, __VA_ARGS__)
|
_litest_add_ranged_no_device(__FILE__, #func_, func_, __VA_ARGS__)
|
||||||
#define litest_add_deviceless(func_) \
|
#define litest_add_deviceless(func_) \
|
||||||
_litest_add_deviceless(__FILE__, #func_, func_)
|
_litest_add_deviceless(__FILE__, #func_, func_)
|
||||||
|
#define litest_add_parametrized_deviceless(func_, params) \
|
||||||
|
_litest_add_parametrize_deviceless(__FILE__, #func_, func_, params)
|
||||||
|
|
||||||
void
|
void
|
||||||
_litest_add(const char *name,
|
_litest_add(const char *name,
|
||||||
|
|
@ -618,6 +685,13 @@ _litest_add_ranged(const char *name,
|
||||||
int64_t excluded,
|
int64_t excluded,
|
||||||
const struct range *range);
|
const struct range *range);
|
||||||
void
|
void
|
||||||
|
_litest_add_parametrized(const char *name,
|
||||||
|
const char *funcname,
|
||||||
|
const void *func,
|
||||||
|
int64_t required,
|
||||||
|
int64_t excluded,
|
||||||
|
struct litest_parameters *params);
|
||||||
|
void
|
||||||
_litest_add_for_device(const char *name,
|
_litest_add_for_device(const char *name,
|
||||||
const char *funcname,
|
const char *funcname,
|
||||||
const void *func,
|
const void *func,
|
||||||
|
|
@ -629,10 +703,21 @@ _litest_add_ranged_for_device(const char *name,
|
||||||
enum litest_device_type type,
|
enum litest_device_type type,
|
||||||
const struct range *range);
|
const struct range *range);
|
||||||
void
|
void
|
||||||
|
_litest_add_parametrized_for_device(const char *name,
|
||||||
|
const char *funcname,
|
||||||
|
const void *func,
|
||||||
|
enum litest_device_type type,
|
||||||
|
struct litest_parameters *params);
|
||||||
|
void
|
||||||
_litest_add_no_device(const char *name,
|
_litest_add_no_device(const char *name,
|
||||||
const char *funcname,
|
const char *funcname,
|
||||||
const void *func);
|
const void *func);
|
||||||
void
|
void
|
||||||
|
_litest_add_parametrized_no_device(const char *name,
|
||||||
|
const char *funcname,
|
||||||
|
const void *func,
|
||||||
|
struct litest_parameters *params);
|
||||||
|
void
|
||||||
_litest_add_ranged_no_device(const char *name,
|
_litest_add_ranged_no_device(const char *name,
|
||||||
const char *funcname,
|
const char *funcname,
|
||||||
const void *func,
|
const void *func,
|
||||||
|
|
@ -641,6 +726,11 @@ void
|
||||||
_litest_add_deviceless(const char *name,
|
_litest_add_deviceless(const char *name,
|
||||||
const char *funcname,
|
const char *funcname,
|
||||||
const void *func);
|
const void *func);
|
||||||
|
void
|
||||||
|
_litest_add_parametrized_deviceless(const char *name,
|
||||||
|
const char *funcname,
|
||||||
|
const void *func,
|
||||||
|
struct litest_parameters *params);
|
||||||
|
|
||||||
struct litest_device *
|
struct litest_device *
|
||||||
litest_create_device(enum litest_device_type which);
|
litest_create_device(enum litest_device_type which);
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,11 @@ START_TEST(log_axisrange_warning)
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
struct libinput *li = dev->libinput;
|
struct libinput *li = dev->libinput;
|
||||||
const struct input_absinfo *abs;
|
const struct input_absinfo *abs;
|
||||||
int axis = _i; /* looped test */
|
|
||||||
|
const char *axisname;
|
||||||
|
litest_test_param_fetch(test_env->params, "axis", &axisname);
|
||||||
|
int axis = libevdev_event_code_from_code_name(axisname);
|
||||||
|
litest_assert_int_ne(axis, -1);
|
||||||
|
|
||||||
litest_touch_down(dev, 0, 90, 100);
|
litest_touch_down(dev, 0, 90, 100);
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
@ -202,14 +206,16 @@ END_TEST
|
||||||
|
|
||||||
TEST_COLLECTION(log)
|
TEST_COLLECTION(log)
|
||||||
{
|
{
|
||||||
struct range axes = { ABS_X, ABS_Y + 1};
|
|
||||||
|
|
||||||
litest_add_deviceless(log_default_priority);
|
litest_add_deviceless(log_default_priority);
|
||||||
litest_add_deviceless(log_handler_invoked);
|
litest_add_deviceless(log_handler_invoked);
|
||||||
litest_add_deviceless(log_handler_NULL);
|
litest_add_deviceless(log_handler_NULL);
|
||||||
litest_add_no_device(log_priority);
|
litest_add_no_device(log_priority);
|
||||||
|
|
||||||
|
{
|
||||||
|
struct litest_parameters *params = litest_parameters_new("axis", 's', 2, "ABS_X", "ABS_Y");
|
||||||
/* mtdev clips to axis ranges */
|
/* mtdev clips to axis ranges */
|
||||||
litest_add_ranged(log_axisrange_warning, LITEST_TOUCH, LITEST_PROTOCOL_A, &axes);
|
litest_add_parametrized(log_axisrange_warning, LITEST_TOUCH, LITEST_PROTOCOL_A, params);
|
||||||
litest_add_ranged(log_axisrange_warning, LITEST_TOUCHPAD, LITEST_ANY, &axes);
|
litest_add_parametrized(log_axisrange_warning, LITEST_TOUCHPAD, LITEST_ANY, params);
|
||||||
|
litest_parameters_unref(params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -183,26 +183,32 @@ START_TEST(pointer_motion_relative_min_decel)
|
||||||
struct libinput_event *event;
|
struct libinput_event *event;
|
||||||
double evx, evy;
|
double evx, evy;
|
||||||
int dx, dy;
|
int dx, dy;
|
||||||
int cardinal = _i; /* ranged test */
|
|
||||||
double len;
|
double len;
|
||||||
|
|
||||||
int deltas[8][2] = {
|
const char *direction;
|
||||||
/* N, NE, E, ... */
|
litest_test_param_fetch(test_env->params, "direction", &direction, NULL);
|
||||||
{ 0, 1 },
|
|
||||||
{ 1, 1 },
|
if (streq(direction, "N")) {
|
||||||
{ 1, 0 },
|
dx = 0; dy = 1;
|
||||||
{ 1, -1 },
|
} else if (streq(direction, "NE")) {
|
||||||
{ 0, -1 },
|
dx = 1; dy = 1;
|
||||||
{ -1, -1 },
|
} else if (streq(direction, "E")) {
|
||||||
{ -1, 0 },
|
dx = 1; dy = 0;
|
||||||
{ -1, 1 },
|
} else if (streq(direction, "SE")) {
|
||||||
};
|
dx = 1; dy = -1;
|
||||||
|
} else if (streq(direction, "S")) {
|
||||||
|
dx = 0; dy = -1;
|
||||||
|
} else if (streq(direction, "SW")) {
|
||||||
|
dx = -1; dy = -1;
|
||||||
|
} else if (streq(direction, "W")) {
|
||||||
|
dx = -1; dy = 0;
|
||||||
|
} else if (streq(direction, "NW")) {
|
||||||
|
dx = -1, dy = 1;
|
||||||
|
} else
|
||||||
|
litest_abort_msg("Invalid direction %s", direction);
|
||||||
|
|
||||||
litest_drain_events(dev->libinput);
|
litest_drain_events(dev->libinput);
|
||||||
|
|
||||||
dx = deltas[cardinal][0];
|
|
||||||
dy = deltas[cardinal][1];
|
|
||||||
|
|
||||||
litest_event(dev, EV_REL, REL_X, dx);
|
litest_event(dev, EV_REL, REL_X, dx);
|
||||||
litest_event(dev, EV_REL, REL_Y, dy);
|
litest_event(dev, EV_REL, REL_Y, dy);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
|
@ -268,7 +274,11 @@ START_TEST(pointer_absolute_initial_state)
|
||||||
struct libinput *libinput1, *libinput2;
|
struct libinput *libinput1, *libinput2;
|
||||||
struct libinput_event *ev1, *ev2;
|
struct libinput_event *ev1, *ev2;
|
||||||
struct libinput_event_pointer *p1, *p2;
|
struct libinput_event_pointer *p1, *p2;
|
||||||
int axis = _i; /* looped test */
|
|
||||||
|
const char *axisname;
|
||||||
|
litest_test_param_fetch(test_env->params, "axis", &axisname);
|
||||||
|
int axis = libevdev_event_code_from_code_name(axisname);
|
||||||
|
litest_assert_int_ne(axis, -1);
|
||||||
|
|
||||||
libinput1 = dev->libinput;
|
libinput1 = dev->libinput;
|
||||||
litest_touch_down(dev, 0, 40, 60);
|
litest_touch_down(dev, 0, 40, 60);
|
||||||
|
|
@ -767,23 +777,22 @@ START_TEST(pointer_scroll_wheel_hires_send_only_lores)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
struct libinput *li = dev->libinput;
|
struct libinput *li = dev->libinput;
|
||||||
enum libinput_pointer_axis axis = _i; /* ranged test */
|
|
||||||
unsigned int lores_code, hires_code;
|
unsigned int lores_code, hires_code;
|
||||||
int direction;
|
int direction;
|
||||||
|
|
||||||
switch (axis) {
|
const char *axisname;
|
||||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
litest_test_param_fetch(test_env->params, "axis", &axisname, NULL);
|
||||||
|
|
||||||
|
if (streq(axisname, "vertical")) {
|
||||||
lores_code = REL_WHEEL;
|
lores_code = REL_WHEEL;
|
||||||
hires_code = REL_WHEEL_HI_RES;
|
hires_code = REL_WHEEL_HI_RES;
|
||||||
direction = -1;
|
direction = -1;
|
||||||
break;
|
} else if (streq(axisname, "horizontal")) {
|
||||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
|
||||||
lores_code = REL_HWHEEL;
|
lores_code = REL_HWHEEL;
|
||||||
hires_code = REL_HWHEEL_HI_RES;
|
hires_code = REL_HWHEEL_HI_RES;
|
||||||
direction = 1;
|
direction = 1;
|
||||||
break;
|
} else {
|
||||||
default:
|
litest_abort_msg("Invalid test axis '%s'", axisname);
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!libevdev_has_event_code(dev->evdev, EV_REL, lores_code) &&
|
if (!libevdev_has_event_code(dev->evdev, EV_REL, lores_code) &&
|
||||||
|
|
@ -3745,17 +3754,19 @@ END_TEST
|
||||||
|
|
||||||
TEST_COLLECTION(pointer)
|
TEST_COLLECTION(pointer)
|
||||||
{
|
{
|
||||||
struct range axis_range = {ABS_X, ABS_Y + 1};
|
|
||||||
struct range compass = {0, 7}; /* cardinal directions */
|
|
||||||
struct range buttons = {BTN_LEFT, BTN_TASK + 1};
|
struct range buttons = {BTN_LEFT, BTN_TASK + 1};
|
||||||
struct range buttonorder = {0, _MB_BUTTONORDER_COUNT};
|
struct range buttonorder = {0, _MB_BUTTONORDER_COUNT};
|
||||||
struct range scroll_directions = {LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
|
||||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL + 1};
|
|
||||||
struct range rotation_20deg = {0, 18}; /* steps of 20 degrees */
|
struct range rotation_20deg = {0, 18}; /* steps of 20 degrees */
|
||||||
|
|
||||||
litest_add(pointer_motion_relative, LITEST_RELATIVE, LITEST_POINTINGSTICK);
|
litest_add(pointer_motion_relative, LITEST_RELATIVE, LITEST_POINTINGSTICK);
|
||||||
litest_add_for_device(pointer_motion_relative_zero, LITEST_MOUSE);
|
litest_add_for_device(pointer_motion_relative_zero, LITEST_MOUSE);
|
||||||
litest_add_ranged(pointer_motion_relative_min_decel, LITEST_RELATIVE, LITEST_POINTINGSTICK, &compass);
|
{
|
||||||
|
struct litest_parameters *params = litest_parameters_new("direction", 's', 8,
|
||||||
|
"N", "E", "S", "W",
|
||||||
|
"NE", "SE", "SW", "NW");
|
||||||
|
litest_add_parametrized(pointer_motion_relative_min_decel, LITEST_RELATIVE, LITEST_POINTINGSTICK, params);
|
||||||
|
litest_parameters_unref(params);
|
||||||
|
}
|
||||||
litest_add(pointer_motion_absolute, LITEST_ABSOLUTE, LITEST_ANY);
|
litest_add(pointer_motion_absolute, LITEST_ABSOLUTE, LITEST_ANY);
|
||||||
litest_add(pointer_motion_unaccel, LITEST_RELATIVE, LITEST_ANY);
|
litest_add(pointer_motion_unaccel, LITEST_RELATIVE, LITEST_ANY);
|
||||||
litest_add(pointer_button, LITEST_BUTTON, LITEST_CLICKPAD);
|
litest_add(pointer_button, LITEST_BUTTON, LITEST_CLICKPAD);
|
||||||
|
|
@ -3765,7 +3776,11 @@ TEST_COLLECTION(pointer)
|
||||||
litest_add(pointer_recover_from_lost_button_count, LITEST_BUTTON, LITEST_CLICKPAD);
|
litest_add(pointer_recover_from_lost_button_count, LITEST_BUTTON, LITEST_CLICKPAD);
|
||||||
litest_add(pointer_scroll_wheel, LITEST_WHEEL, LITEST_TABLET);
|
litest_add(pointer_scroll_wheel, LITEST_WHEEL, LITEST_TABLET);
|
||||||
litest_add(pointer_scroll_wheel_hires, LITEST_WHEEL, LITEST_TABLET);
|
litest_add(pointer_scroll_wheel_hires, LITEST_WHEEL, LITEST_TABLET);
|
||||||
litest_add_ranged(pointer_scroll_wheel_hires_send_only_lores, LITEST_WHEEL, LITEST_TABLET, &scroll_directions);
|
{
|
||||||
|
struct litest_parameters *params = litest_parameters_new("axis", 's', 2, "vertical", "horizontal");
|
||||||
|
litest_add_parametrized(pointer_scroll_wheel_hires_send_only_lores, LITEST_WHEEL, LITEST_TABLET, params);
|
||||||
|
litest_parameters_unref(params);
|
||||||
|
}
|
||||||
litest_add(pointer_scroll_wheel_inhibit_small_deltas, LITEST_WHEEL, LITEST_TABLET);
|
litest_add(pointer_scroll_wheel_inhibit_small_deltas, LITEST_WHEEL, LITEST_TABLET);
|
||||||
litest_add(pointer_scroll_wheel_inhibit_dir_change, LITEST_WHEEL, LITEST_TABLET);
|
litest_add(pointer_scroll_wheel_inhibit_dir_change, LITEST_WHEEL, LITEST_TABLET);
|
||||||
litest_add_for_device(pointer_scroll_wheel_lenovo_scrollpoint, LITEST_LENOVO_SCROLLPOINT);
|
litest_add_for_device(pointer_scroll_wheel_lenovo_scrollpoint, LITEST_LENOVO_SCROLLPOINT);
|
||||||
|
|
@ -3833,7 +3848,11 @@ TEST_COLLECTION(pointer)
|
||||||
litest_add(middlebutton_device_remove_while_down, LITEST_BUTTON, LITEST_CLICKPAD);
|
litest_add(middlebutton_device_remove_while_down, LITEST_BUTTON, LITEST_CLICKPAD);
|
||||||
litest_add(middlebutton_device_remove_while_one_is_down, LITEST_BUTTON, LITEST_CLICKPAD);
|
litest_add(middlebutton_device_remove_while_one_is_down, LITEST_BUTTON, LITEST_CLICKPAD);
|
||||||
|
|
||||||
litest_add_ranged(pointer_absolute_initial_state, LITEST_ABSOLUTE, LITEST_ANY, &axis_range);
|
{
|
||||||
|
struct litest_parameters *params = litest_parameters_new("axis", 's', 2, "ABS_X", "ABS_Y");
|
||||||
|
litest_add_parametrized(pointer_absolute_initial_state, LITEST_ABSOLUTE, LITEST_ANY, params);
|
||||||
|
litest_parameters_unref(params);
|
||||||
|
}
|
||||||
|
|
||||||
litest_add(pointer_time_usec, LITEST_RELATIVE, LITEST_ANY);
|
litest_add(pointer_time_usec, LITEST_RELATIVE, LITEST_ANY);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -815,7 +815,11 @@ START_TEST(touch_initial_state)
|
||||||
struct libinput_event *ev2 = NULL;
|
struct libinput_event *ev2 = NULL;
|
||||||
struct libinput_event_touch *t1, *t2;
|
struct libinput_event_touch *t1, *t2;
|
||||||
struct libinput_device *device1, *device2;
|
struct libinput_device *device1, *device2;
|
||||||
int axis = _i; /* looped test */
|
|
||||||
|
const char *axisname;
|
||||||
|
litest_test_param_fetch(test_env->params, "axis", &axisname);
|
||||||
|
int axis = libevdev_event_code_from_code_name(axisname);
|
||||||
|
litest_assert_int_ne(axis, -1);
|
||||||
|
|
||||||
dev = litest_current_device();
|
dev = litest_current_device();
|
||||||
device1 = dev->libinput_device;
|
device1 = dev->libinput_device;
|
||||||
|
|
@ -1336,8 +1340,6 @@ END_TEST
|
||||||
|
|
||||||
TEST_COLLECTION(touch)
|
TEST_COLLECTION(touch)
|
||||||
{
|
{
|
||||||
struct range axes = { ABS_X, ABS_Y + 1};
|
|
||||||
|
|
||||||
litest_add(touch_frame_events, LITEST_TOUCH, LITEST_ANY);
|
litest_add(touch_frame_events, LITEST_TOUCH, LITEST_ANY);
|
||||||
litest_add(touch_downup_no_motion, LITEST_TOUCH, LITEST_ANY);
|
litest_add(touch_downup_no_motion, LITEST_TOUCH, LITEST_ANY);
|
||||||
litest_add(touch_downup_no_motion, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD);
|
litest_add(touch_downup_no_motion, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD);
|
||||||
|
|
@ -1364,7 +1366,11 @@ TEST_COLLECTION(touch)
|
||||||
litest_add(touch_protocol_a_touch, LITEST_PROTOCOL_A, LITEST_ANY);
|
litest_add(touch_protocol_a_touch, LITEST_PROTOCOL_A, LITEST_ANY);
|
||||||
litest_add(touch_protocol_a_2fg_touch, LITEST_PROTOCOL_A, LITEST_ANY);
|
litest_add(touch_protocol_a_2fg_touch, LITEST_PROTOCOL_A, LITEST_ANY);
|
||||||
|
|
||||||
litest_add_ranged(touch_initial_state, LITEST_TOUCH, LITEST_PROTOCOL_A, &axes);
|
{
|
||||||
|
struct litest_parameters *params = litest_parameters_new("axis", 's', 2, "ABS_X", "ABS_Y");
|
||||||
|
litest_add_parametrized(touch_initial_state, LITEST_TOUCH, LITEST_PROTOCOL_A, params);
|
||||||
|
litest_parameters_unref(params);
|
||||||
|
}
|
||||||
|
|
||||||
litest_add(touch_time_usec, LITEST_TOUCH, LITEST_TOUCHPAD);
|
litest_add(touch_time_usec, LITEST_TOUCH, LITEST_TOUCHPAD);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1833,10 +1833,6 @@ START_TEST(multivalue_test)
|
||||||
litest_assert_int_eq(v.type, 's');
|
litest_assert_int_eq(v.type, 's');
|
||||||
litest_assert_str_eq(v.value.s, "test");
|
litest_assert_str_eq(v.value.s, "test");
|
||||||
|
|
||||||
char *str = multivalue_as_str(&v);
|
|
||||||
litest_assert_str_eq(str, "test");
|
|
||||||
free(str);
|
|
||||||
|
|
||||||
const char *s;
|
const char *s;
|
||||||
multivalue_extract_typed(&v, 's', &s);
|
multivalue_extract_typed(&v, 's', &s);
|
||||||
litest_assert_str_eq(s, "test");
|
litest_assert_str_eq(s, "test");
|
||||||
|
|
@ -1851,6 +1847,10 @@ START_TEST(multivalue_test)
|
||||||
char *p1 = copy.value.s;
|
char *p1 = copy.value.s;
|
||||||
char *p2 = v.value.s;
|
char *p2 = v.value.s;
|
||||||
litest_assert_ptr_ne(p1, p2);
|
litest_assert_ptr_ne(p1, p2);
|
||||||
|
|
||||||
|
char *str = multivalue_as_str(&v);
|
||||||
|
litest_assert_str_eq(str, "test");
|
||||||
|
free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -1858,10 +1858,6 @@ START_TEST(multivalue_test)
|
||||||
litest_assert_int_eq(v.type, 'c');
|
litest_assert_int_eq(v.type, 'c');
|
||||||
litest_assert_int_eq(v.value.c, 'x');
|
litest_assert_int_eq(v.value.c, 'x');
|
||||||
|
|
||||||
char *str = multivalue_as_str(&v);
|
|
||||||
litest_assert_str_eq(str, "x");
|
|
||||||
free(str);
|
|
||||||
|
|
||||||
char c;
|
char c;
|
||||||
multivalue_extract_typed(&v, 'c', &c);
|
multivalue_extract_typed(&v, 'c', &c);
|
||||||
litest_assert_int_eq(c, 'x');
|
litest_assert_int_eq(c, 'x');
|
||||||
|
|
@ -1871,6 +1867,10 @@ START_TEST(multivalue_test)
|
||||||
struct multivalue copy = multivalue_copy(&v);
|
struct multivalue copy = multivalue_copy(&v);
|
||||||
litest_assert_int_eq(copy.type, v.type);
|
litest_assert_int_eq(copy.type, v.type);
|
||||||
litest_assert_int_eq(copy.value.c, v.value.c);
|
litest_assert_int_eq(copy.value.c, v.value.c);
|
||||||
|
|
||||||
|
char *str = multivalue_as_str(&v);
|
||||||
|
litest_assert_str_eq(str, "x");
|
||||||
|
free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -1878,10 +1878,6 @@ START_TEST(multivalue_test)
|
||||||
litest_assert_int_eq(v.type, 'u');
|
litest_assert_int_eq(v.type, 'u');
|
||||||
litest_assert_int_eq(v.value.u, 0x1234u);
|
litest_assert_int_eq(v.value.u, 0x1234u);
|
||||||
|
|
||||||
char *str = multivalue_as_str(&v);
|
|
||||||
litest_assert_str_eq(str, "4660");
|
|
||||||
free(str);
|
|
||||||
|
|
||||||
uint32_t c;
|
uint32_t c;
|
||||||
multivalue_extract_typed(&v, 'u', &c);
|
multivalue_extract_typed(&v, 'u', &c);
|
||||||
litest_assert_int_eq(c, 0x1234u);
|
litest_assert_int_eq(c, 0x1234u);
|
||||||
|
|
@ -1891,6 +1887,10 @@ START_TEST(multivalue_test)
|
||||||
struct multivalue copy = multivalue_copy(&v);
|
struct multivalue copy = multivalue_copy(&v);
|
||||||
litest_assert_int_eq(copy.type, v.type);
|
litest_assert_int_eq(copy.type, v.type);
|
||||||
litest_assert_int_eq(copy.value.u, v.value.u);
|
litest_assert_int_eq(copy.value.u, v.value.u);
|
||||||
|
|
||||||
|
char *str = multivalue_as_str(&v);
|
||||||
|
litest_assert_str_eq(str, "4660");
|
||||||
|
free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -1898,10 +1898,6 @@ START_TEST(multivalue_test)
|
||||||
litest_assert_int_eq(v.type, 'i');
|
litest_assert_int_eq(v.type, 'i');
|
||||||
litest_assert_int_eq(v.value.i, -123);
|
litest_assert_int_eq(v.value.i, -123);
|
||||||
|
|
||||||
char *str = multivalue_as_str(&v);
|
|
||||||
litest_assert_str_eq(str, "-123");
|
|
||||||
free(str);
|
|
||||||
|
|
||||||
int32_t c;
|
int32_t c;
|
||||||
multivalue_extract_typed(&v, 'i', &c);
|
multivalue_extract_typed(&v, 'i', &c);
|
||||||
litest_assert_int_eq(c, -123);
|
litest_assert_int_eq(c, -123);
|
||||||
|
|
@ -1911,6 +1907,10 @@ START_TEST(multivalue_test)
|
||||||
struct multivalue copy = multivalue_copy(&v);
|
struct multivalue copy = multivalue_copy(&v);
|
||||||
litest_assert_int_eq(copy.type, v.type);
|
litest_assert_int_eq(copy.type, v.type);
|
||||||
litest_assert_int_eq(copy.value.i, v.value.i);
|
litest_assert_int_eq(copy.value.i, v.value.i);
|
||||||
|
|
||||||
|
char *str = multivalue_as_str(&v);
|
||||||
|
litest_assert_str_eq(str, "-123");
|
||||||
|
free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -1918,10 +1918,6 @@ START_TEST(multivalue_test)
|
||||||
litest_assert_int_eq(v.type, 'b');
|
litest_assert_int_eq(v.type, 'b');
|
||||||
litest_assert_int_eq(v.value.b, true);
|
litest_assert_int_eq(v.value.b, true);
|
||||||
|
|
||||||
char *str = multivalue_as_str(&v);
|
|
||||||
litest_assert_str_eq(str, "true");
|
|
||||||
free(str);
|
|
||||||
|
|
||||||
bool c;
|
bool c;
|
||||||
multivalue_extract_typed(&v, 'b', &c);
|
multivalue_extract_typed(&v, 'b', &c);
|
||||||
litest_assert_int_eq(c, true);
|
litest_assert_int_eq(c, true);
|
||||||
|
|
@ -1931,6 +1927,10 @@ START_TEST(multivalue_test)
|
||||||
struct multivalue copy = multivalue_copy(&v);
|
struct multivalue copy = multivalue_copy(&v);
|
||||||
litest_assert_int_eq(copy.type, v.type);
|
litest_assert_int_eq(copy.type, v.type);
|
||||||
litest_assert_int_eq(copy.value.b, v.value.b);
|
litest_assert_int_eq(copy.value.b, v.value.b);
|
||||||
|
|
||||||
|
char *str = multivalue_as_str(&v);
|
||||||
|
litest_assert_str_eq(str, "true");
|
||||||
|
free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -1938,10 +1938,6 @@ START_TEST(multivalue_test)
|
||||||
litest_assert_int_eq(v.type, 'd');
|
litest_assert_int_eq(v.type, 'd');
|
||||||
litest_assert_double_eq(v.value.d, 0.1234);
|
litest_assert_double_eq(v.value.d, 0.1234);
|
||||||
|
|
||||||
char *str = multivalue_as_str(&v);
|
|
||||||
litest_assert_str_eq(str, "0.123400");
|
|
||||||
free(str);
|
|
||||||
|
|
||||||
double c;
|
double c;
|
||||||
multivalue_extract_typed(&v, 'd', &c);
|
multivalue_extract_typed(&v, 'd', &c);
|
||||||
litest_assert_double_eq(c, 0.1234);
|
litest_assert_double_eq(c, 0.1234);
|
||||||
|
|
@ -1951,6 +1947,10 @@ START_TEST(multivalue_test)
|
||||||
struct multivalue copy = multivalue_copy(&v);
|
struct multivalue copy = multivalue_copy(&v);
|
||||||
litest_assert_int_eq(copy.type, v.type);
|
litest_assert_int_eq(copy.type, v.type);
|
||||||
litest_assert_double_eq(copy.value.d, v.value.d);
|
litest_assert_double_eq(copy.value.d, v.value.d);
|
||||||
|
|
||||||
|
char *str = multivalue_as_str(&v);
|
||||||
|
litest_assert_str_eq(str, "0.123400");
|
||||||
|
free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue