test: add a backtrace facility to litest

The check unit test framework isn't particularly suited to having ck_assert*
calls in helper functions. A failed assertion in a helper function or the
litest framework merely gives us a the failed line in litest.c.
which doesn't tell us which test actually failed.

Add a backtracing facility with litest_backtrace(). And since this requires
wrapping all ck_assert macros with litest_assert() this patch ended up
replacing/duplicating a bunch of ck_assert_* bits. So rather than
ck_assert_int_eq() we now use litest_assert_int_eq(), etc. in the litest
framework itself.

The int comparison macros are more type-safe than ck_assert()'s macros which
just cast all the ints to intmax_t.

Backtrace is spewed to stderr, which is good enough for debugging. Example
backtrace:

	FAILED COMPARISON: status != expected
	Resolved to: 0 != 0
	in disable_button_scrolling() (pointer.c:115)

	Backtrace:
	0: ./test/test-pointer (litest_fail_comparison_int+0xab) [0x40973b]
	1: ./test/test-pointer (disable_button_scrolling+0x174) [0x40421b]
	2: ./test/test-pointer (middlebutton_middleclick+0x40) [0x40829c]
	3: /lib64/libcheck.so.0 (srunner_run+0x7f5) [0x7f0e8a277025]
	4: ./test/test-pointer (litest_run+0x107) [0x40a42b]
	5: ./test/test-pointer (main+0x2fa) [0x4090e7]
	6: /lib64/libc.so.6 (__libc_start_main+0xf0) [0x7f0e88f5e790]
	7: ./test/test-pointer (_start+0x29) [0x403ce9]
	8: ? (?+0x29) [0x29]

litest_backtrace() itself is copied from xserver/os/backtrace.c which git
blame attributes to Marcin.

CC:  Marcin Slusarz <marcin.slusarz@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2015-05-04 09:13:22 +10:00
parent c9ea9836f3
commit 84e6321f51
6 changed files with 537 additions and 70 deletions

View file

@ -60,6 +60,15 @@ PKG_PROG_PKG_CONFIG()
PKG_CHECK_MODULES(MTDEV, [mtdev >= 1.1.0])
PKG_CHECK_MODULES(LIBUDEV, [libudev])
PKG_CHECK_MODULES(LIBEVDEV, [libevdev >= 0.4])
PKG_CHECK_MODULES(LIBUNWIND,
[libunwind],
[HAVE_LIBUNWIND=yes],
[HAVE_LIBUNWIND=no])
if test "x$HAVE_LIBUNWIND" = "xyes"; then
AC_DEFINE(HAVE_LIBUNWIND, 1, [Have libunwind support])
fi
AM_CONDITIONAL(HAVE_LIBUNWIND, [test "x$HAVE_LIBUNWIND" = xyes])
AC_CHECK_LIB([m], [atan2])
AC_CHECK_LIB([rt], [clock_gettime])
@ -190,5 +199,6 @@ AC_MSG_RESULT([
Build documentation ${build_documentation}
Build tests ${build_tests}
Tests use valgrind ${VALGRIND}
Tests use libunwind ${HAVE_LIBUNWIND}
Build GUI event tool ${build_eventgui}
])

View file

@ -38,6 +38,11 @@ liblitest_la_SOURCES = \
litest-vmware-virtual-usb-mouse.c \
litest.c
liblitest_la_LIBADD = $(top_builddir)/src/libinput-util.la
liblitest_la_CFLAGS = $(AM_CFLAGS)
if HAVE_LIBUNWIND
liblitest_la_LIBADD += $(LIBUNWIND_LIBS) -ldl
liblitest_la_CFLAGS += $(LIBUNWIND_CFLAGS)
endif
run_tests = \
test-touchpad \
@ -49,7 +54,9 @@ run_tests = \
test-path \
test-log \
test-misc \
test-keyboard
test-keyboard \
test-litest-selftest
build_tests = \
test-build-cxx \
test-build-linker \
@ -102,6 +109,11 @@ test_device_SOURCES = device.c
test_device_LDADD = $(TEST_LIBS)
test_device_LDFLAGS = -no-install
test_litest_selftest_SOURCES = litest-selftest.c litest.c litest-int.h litest.h
test_litest_selftest_CFLAGS = -DLITEST_DISABLE_BACKTRACE_LOGGING
test_litest_selftest_LDADD = $(TEST_LIBS)
test_litest_selftest_LDFLAGS = -no-install
# build-test only
test_build_pedantic_c99_SOURCES = build-pedantic.c
test_build_pedantic_c99_CFLAGS = -std=c99 -pedantic -Werror
@ -125,7 +137,7 @@ VALGRIND_FLAGS=--leak-check=full \
--suppressions=$(srcdir)/valgrind.suppressions
valgrind:
$(MAKE) check-TESTS LOG_COMPILER="$(VALGRIND)" LOG_FLAGS="$(VALGRIND_FLAGS)" CK_FORK=no
$(MAKE) check-TESTS LOG_COMPILER="$(VALGRIND)" LOG_FLAGS="$(VALGRIND_FLAGS)" CK_FORK=no USING_VALGRIND=yes
check: valgrind

228
test/litest-selftest.c Normal file
View file

@ -0,0 +1,228 @@
#include <config.h>
#include <check.h>
#include <signal.h>
#include "litest.h"
START_TEST(litest_assert_trigger)
{
litest_assert(1 == 2);
}
END_TEST
START_TEST(litest_assert_notrigger)
{
litest_assert(1 == 1);
}
END_TEST
START_TEST(litest_assert_msg_trigger)
{
litest_assert_msg(1 == 2, "1 is not 2\n");
}
END_TEST
START_TEST(litest_assert_msg_NULL_trigger)
{
litest_assert_msg(1 == 2, NULL);
}
END_TEST
START_TEST(litest_assert_msg_notrigger)
{
litest_assert_msg(1 == 1, "1 is not 2\n");
litest_assert_msg(1 == 1, NULL);
}
END_TEST
START_TEST(litest_abort_msg_trigger)
{
litest_abort_msg("message\n");
}
END_TEST
START_TEST(litest_abort_msg_NULL_trigger)
{
litest_abort_msg(NULL);
}
END_TEST
START_TEST(litest_int_eq_trigger)
{
int a = 10;
int b = 20;
litest_assert_int_eq(a, b);
}
END_TEST
START_TEST(litest_int_eq_notrigger)
{
int a = 10;
int b = 10;
litest_assert_int_eq(a, b);
}
END_TEST
START_TEST(litest_int_ne_trigger)
{
int a = 10;
int b = 10;
litest_assert_int_ne(a, b);
}
END_TEST
START_TEST(litest_int_ne_notrigger)
{
int a = 10;
int b = 20;
litest_assert_int_ne(a, b);
}
END_TEST
START_TEST(litest_int_lt_trigger_eq)
{
int a = 10;
int b = 10;
litest_assert_int_lt(a, b);
}
END_TEST
START_TEST(litest_int_lt_trigger_gt)
{
int a = 11;
int b = 10;
litest_assert_int_lt(a, b);
}
END_TEST
START_TEST(litest_int_lt_notrigger)
{
int a = 10;
int b = 11;
litest_assert_int_lt(a, b);
}
END_TEST
START_TEST(litest_int_le_trigger)
{
int a = 11;
int b = 10;
litest_assert_int_le(a, b);
}
END_TEST
START_TEST(litest_int_le_notrigger)
{
int a = 10;
int b = 11;
int c = 10;
litest_assert_int_le(a, b);
litest_assert_int_le(a, c);
}
END_TEST
START_TEST(litest_int_gt_trigger_eq)
{
int a = 10;
int b = 10;
litest_assert_int_gt(a, b);
}
END_TEST
START_TEST(litest_int_gt_trigger_lt)
{
int a = 9;
int b = 10;
litest_assert_int_gt(a, b);
}
END_TEST
START_TEST(litest_int_gt_notrigger)
{
int a = 10;
int b = 9;
litest_assert_int_gt(a, b);
}
END_TEST
START_TEST(litest_int_ge_trigger)
{
int a = 9;
int b = 10;
litest_assert_int_ge(a, b);
}
END_TEST
START_TEST(litest_int_ge_notrigger)
{
int a = 10;
int b = 9;
int c = 10;
litest_assert_int_ge(a, b);
litest_assert_int_ge(a, c);
}
END_TEST
static Suite *
litest_assert_macros_suite(void)
{
TCase *tc;
Suite *s;
s = suite_create("litest:assert macros");
tc = tcase_create("assert");
tcase_add_test_raise_signal(tc, litest_assert_trigger, SIGABRT);
tcase_add_test(tc, litest_assert_notrigger);
tcase_add_test_raise_signal(tc, litest_assert_msg_trigger, SIGABRT);
tcase_add_test_raise_signal(tc, litest_assert_msg_NULL_trigger, SIGABRT);
tcase_add_test(tc, litest_assert_msg_notrigger);
suite_add_tcase(s, tc);
tc = tcase_create("abort");
tcase_add_test_raise_signal(tc, litest_abort_msg_trigger, SIGABRT);
tcase_add_test_raise_signal(tc, litest_abort_msg_NULL_trigger, SIGABRT);
suite_add_tcase(s, tc);
tc = tcase_create("int comparison ");
tcase_add_test_raise_signal(tc, litest_int_eq_trigger, SIGABRT);
tcase_add_test(tc, litest_int_eq_notrigger);
tcase_add_test_raise_signal(tc, litest_int_ne_trigger, SIGABRT);
tcase_add_test(tc, litest_int_ne_notrigger);
tcase_add_test_raise_signal(tc, litest_int_le_trigger, SIGABRT);
tcase_add_test(tc, litest_int_le_notrigger);
tcase_add_test_raise_signal(tc, litest_int_lt_trigger_gt, SIGABRT);
tcase_add_test_raise_signal(tc, litest_int_lt_trigger_eq, SIGABRT);
tcase_add_test(tc, litest_int_lt_notrigger);
tcase_add_test_raise_signal(tc, litest_int_ge_trigger, SIGABRT);
tcase_add_test(tc, litest_int_ge_notrigger);
tcase_add_test_raise_signal(tc, litest_int_gt_trigger_eq, SIGABRT);
tcase_add_test_raise_signal(tc, litest_int_gt_trigger_lt, SIGABRT);
tcase_add_test(tc, litest_int_gt_notrigger);
suite_add_tcase(s, tc);
return s;
}
int
main (int argc, char **argv)
{
int nfailed;
Suite *s;
SRunner *sr;
/* when running under valgrind we're using nofork mode, so a signal
* raised by a test will fail in valgrind. There's nothing to
* memcheck here anyway, so just skip the valgrind test */
if (getenv("USING_VALGRIND"))
return EXIT_SUCCESS;
s = litest_assert_macros_suite();
sr = srunner_create(s);
srunner_run_all(sr, CK_ENV);
nfailed = srunner_ntests_failed(sr);
srunner_free(sr);
return (nfailed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

View file

@ -1,5 +1,6 @@
/*
* Copyright © 2013 Red Hat, Inc.
* Copyright © 2013 Marcin Slusarz <marcin.slusarz@gmail.com>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@ -51,6 +52,142 @@
static int in_debugger = -1;
static int verbose = 0;
#ifdef HAVE_LIBUNWIND
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <dlfcn.h>
/* defined for the litest selftest */
#ifndef LITEST_DISABLE_BACKTRACE_LOGGING
#define litest_log(...) fprintf(stderr, __VA_ARGS__)
#define litest_vlog(format_, args_) vfprintf(stderr, format_, args_)
#else
#define litest_log(...) /* __VA_ARGS__ */
#define litest_vlog(...) /* __VA_ARGS__ */
#endif
static void
litest_backtrace(void)
{
unw_cursor_t cursor;
unw_context_t context;
unw_word_t off;
unw_proc_info_t pip;
int ret;
char procname[256];
Dl_info dlinfo;
/* filename and i are unused ifdef LITEST_SHUTUP */
const char *filename __attribute__((unused));
int i __attribute__((unused)) = 0;
pip.unwind_info = NULL;
ret = unw_getcontext(&context);
if (ret) {
litest_log("unw_getcontext failed: %s [%d]\n",
unw_strerror(ret),
ret);
return;
}
ret = unw_init_local(&cursor, &context);
if (ret) {
litest_log("unw_init_local failed: %s [%d]\n",
unw_strerror(ret),
ret);
return;
}
litest_log("\nBacktrace:\n");
ret = unw_step(&cursor);
while (ret > 0) {
ret = unw_get_proc_info(&cursor, &pip);
if (ret) {
litest_log("unw_get_proc_info failed: %s [%d]\n",
unw_strerror(ret),
ret);
break;
}
ret = unw_get_proc_name(&cursor, procname, 256, &off);
if (ret && ret != -UNW_ENOMEM) {
if (ret != -UNW_EUNSPEC)
litest_log("unw_get_proc_name failed: %s [%d]\n",
unw_strerror(ret),
ret);
procname[0] = '?';
procname[1] = 0;
}
if (dladdr((void *)(pip.start_ip + off), &dlinfo) &&
dlinfo.dli_fname &&
*dlinfo.dli_fname)
filename = dlinfo.dli_fname;
else
filename = "?";
litest_log("%u: %s (%s%s+%#x) [%p]\n",
i++,
filename,
procname,
ret == -UNW_ENOMEM ? "..." : "",
(int)off,
(void *)(pip.start_ip + off));
ret = unw_step(&cursor);
if (ret < 0)
litest_log("unw_step failed: %s [%d]\n",
unw_strerror(ret),
ret);
}
litest_log("\n");
}
#else /* HAVE_LIBUNWIND */
static inline void
litest_backtrace(void)
{
/* thou shall install libunwind */
}
#endif
void
litest_fail_condition(const char *file,
int line,
const char *func,
const char *condition,
const char *message,
...)
{
litest_log("FAILED: %s\n", condition);
if (message) {
va_list args;
va_start(args, message);
litest_vlog(message, args);
va_end(args);
}
litest_log("in %s() (%s:%d)\n", func, file, line);
litest_backtrace();
abort();
}
void
litest_fail_comparison_int(const char *file,
int line,
const char *func,
const char *operator,
int a,
int b,
const char *astr,
const char *bstr)
{
litest_log("FAILED COMPARISON: %s %s %s\n", astr, operator, bstr);
litest_log("Resolved to: %d %s %d\n", a, operator, b);
litest_log("in %s() (%s:%d)\n", func, file, line);
litest_backtrace();
abort();
}
struct test {
struct list node;
char *name;
@ -370,7 +507,7 @@ litest_add_ranged_for_device(const char *name,
dev++;
}
ck_abort_msg("Invalid test device type");
litest_abort_msg("Invalid test device type");
}
static int
@ -533,13 +670,13 @@ merge_absinfo(const struct input_absinfo *orig,
return NULL;
abs = calloc(sz, sizeof(*abs));
ck_assert(abs != NULL);
litest_assert(abs != NULL);
nelem = 0;
while (orig[nelem].value != -1) {
abs[nelem] = orig[nelem];
nelem++;
ck_assert_int_lt(nelem, sz);
litest_assert_int_lt(nelem, sz);
}
/* just append, if the same axis is present twice, libevdev will
@ -547,10 +684,10 @@ merge_absinfo(const struct input_absinfo *orig,
i = 0;
while (override && override[i].value != -1) {
abs[nelem++] = override[i++];
ck_assert_int_lt(nelem, sz);
litest_assert_int_lt(nelem, sz);
}
ck_assert_int_lt(nelem, sz);
litest_assert_int_lt(nelem, sz);
abs[nelem].value = -1;
return abs;
@ -567,13 +704,13 @@ merge_events(const int *orig, const int *override)
return NULL;
events = calloc(sz, sizeof(int));
ck_assert(events != NULL);
litest_assert(events != NULL);
nelem = 0;
while (orig[nelem] != -1) {
events[nelem] = orig[nelem];
nelem++;
ck_assert_int_lt(nelem, sz);
litest_assert_int_lt(nelem, sz);
}
/* just append, if the same axis is present twice, libevdev will
@ -581,10 +718,10 @@ merge_events(const int *orig, const int *override)
i = 0;
while (override && override[i] != -1) {
events[nelem++] = override[i++];
ck_assert_int_le(nelem, sz);
litest_assert_int_le(nelem, sz);
}
ck_assert_int_lt(nelem, sz);
litest_assert_int_lt(nelem, sz);
events[nelem] = -1;
return events;
@ -610,14 +747,14 @@ litest_init_udev_rules(struct litest_test_device *dev)
UDEV_RULES_D,
UDEV_RULE_PREFIX,
dev->shortname);
ck_assert_int_eq(rc,
(int)(
strlen(UDEV_RULES_D) +
strlen(UDEV_RULE_PREFIX) +
strlen(dev->shortname) + 7));
litest_assert_int_eq(rc,
(int)(
strlen(UDEV_RULES_D) +
strlen(UDEV_RULE_PREFIX) +
strlen(dev->shortname) + 7));
f = fopen(path, "w");
ck_assert_notnull(f);
ck_assert_int_ge(fputs(dev->udev_rule, f), 0);
litest_assert_notnull(f);
litest_assert_int_ge(fputs(dev->udev_rule, f), 0);
fclose(f);
litest_reload_udev_rules();
@ -651,7 +788,7 @@ litest_create(enum litest_device_type which,
ck_abort_msg("Invalid device type %d\n", which);
d = zalloc(sizeof(*d));
ck_assert(d != NULL);
litest_assert(d != NULL);
udev_file = litest_init_udev_rules(*dev);
@ -661,8 +798,7 @@ litest_create(enum litest_device_type which,
if (abs_override || events_override) {
if (udev_file)
unlink(udev_file);
ck_abort_msg("Custom create cannot"
"be overridden");
litest_abort_msg("Custom create cannot be overridden");
}
return d;
@ -691,7 +827,7 @@ litest_create_context(void)
{
struct libinput *libinput =
libinput_path_create_context(&interface, NULL);
ck_assert_notnull(libinput);
litest_assert_notnull(libinput);
libinput_log_set_handler(libinput, litest_log_handler);
if (verbose)
@ -732,16 +868,16 @@ litest_add_device_with_overrides(struct libinput *libinput,
events_override);
path = libevdev_uinput_get_devnode(d->uinput);
ck_assert(path != NULL);
litest_assert(path != NULL);
fd = open(path, O_RDWR|O_NONBLOCK);
ck_assert_int_ne(fd, -1);
litest_assert_int_ne(fd, -1);
rc = libevdev_new_from_fd(fd, &d->evdev);
ck_assert_int_eq(rc, 0);
litest_assert_int_eq(rc, 0);
d->libinput = libinput;
d->libinput_device = libinput_path_add_device(d->libinput, path);
ck_assert(d->libinput_device != NULL);
litest_assert(d->libinput_device != NULL);
libinput_device_ref(d->libinput_device);
if (d->interface) {
@ -836,7 +972,7 @@ litest_event(struct litest_device *d, unsigned int type,
return;
ret = libevdev_uinput_write_event(d->uinput, type, code, value);
ck_assert_int_eq(ret, 0);
litest_assert_int_eq(ret, 0);
}
int
@ -1169,9 +1305,9 @@ int
litest_scale(const struct litest_device *d, unsigned int axis, double val)
{
int min, max;
ck_assert_int_ge((int)val, 0);
ck_assert_int_le((int)val, 100);
ck_assert_int_le(axis, (unsigned int)ABS_Y);
litest_assert_int_ge((int)val, 0);
litest_assert_int_le((int)val, 100);
litest_assert_int_le(axis, (unsigned int)ABS_Y);
min = d->interface->min[axis];
max = d->interface->max[axis];
@ -1352,7 +1488,7 @@ litest_assert_empty_queue(struct libinput *li)
libinput_dispatch(li);
}
ck_assert(empty_queue);
litest_assert(empty_queue);
}
struct libevdev_uinput *
@ -1378,7 +1514,7 @@ litest_create_uinput_device_from_description(const char *name,
const char *devnode;
dev = libevdev_new();
ck_assert(dev != NULL);
litest_assert(dev != NULL);
snprintf(buf, sizeof(buf), "litest %s", name);
libevdev_set_name(dev, buf);
@ -1393,7 +1529,7 @@ litest_create_uinput_device_from_description(const char *name,
while (abs && abs->value != -1) {
rc = libevdev_enable_event_code(dev, EV_ABS,
abs->value, abs);
ck_assert_int_eq(rc, 0);
litest_assert_int_eq(rc, 0);
abs++;
}
@ -1406,7 +1542,7 @@ litest_create_uinput_device_from_description(const char *name,
rc = libevdev_enable_event_code(dev, type, code,
type == EV_ABS ? &default_abs : NULL);
}
ck_assert_int_eq(rc, 0);
litest_assert_int_eq(rc, 0);
}
rc = libevdev_uinput_create_from_device(dev,
@ -1416,16 +1552,16 @@ litest_create_uinput_device_from_description(const char *name,
http://cgit.freedesktop.org/libevdev/commit/?id=debe9b030c8069cdf78307888ef3b65830b25122 */
if (rc == -EBADF)
rc = -EACCES;
ck_assert_msg(rc == 0, "Failed to create uinput device: %s", strerror(-rc));
litest_assert_msg(rc == 0, "Failed to create uinput device: %s", strerror(-rc));
libevdev_free(dev);
devnode = libevdev_uinput_get_devnode(uinput);
ck_assert_notnull(devnode);
litest_assert_notnull(devnode);
fd = open(devnode, O_RDONLY);
ck_assert_int_gt(fd, -1);
litest_assert_int_gt(fd, -1);
rc = libevdev_new_from_fd(fd, &dev);
ck_assert_int_eq(rc, 0);
litest_assert_int_eq(rc, 0);
/* uinput does not yet support setting the resolution, so we set it
* afterwards. This is of course racy as hell but the way we
@ -1437,7 +1573,7 @@ litest_create_uinput_device_from_description(const char *name,
rc = libevdev_kernel_set_abs_info(dev,
abs->value,
abs);
ck_assert_int_eq(rc, 0);
litest_assert_int_eq(rc, 0);
}
abs++;
}
@ -1461,7 +1597,7 @@ litest_create_uinput_abs_device_v(const char *name,
(code = va_arg(args, int)) != -1) {
*event++ = type;
*event++ = code;
ck_assert(event < &events[ARRAY_LENGTH(events) - 2]);
litest_assert(event < &events[ARRAY_LENGTH(events) - 2]);
}
*event++ = -1;
@ -1508,13 +1644,13 @@ litest_is_button_event(struct libinput_event *event,
struct libinput_event_pointer *ptrev;
enum libinput_event_type type = LIBINPUT_EVENT_POINTER_BUTTON;
ck_assert(event != NULL);
ck_assert_int_eq(libinput_event_get_type(event), type);
litest_assert(event != NULL);
litest_assert_int_eq(libinput_event_get_type(event), type);
ptrev = libinput_event_get_pointer_event(event);
ck_assert_int_eq(libinput_event_pointer_get_button(ptrev),
button);
ck_assert_int_eq(libinput_event_pointer_get_button_state(ptrev),
state);
litest_assert_int_eq(libinput_event_pointer_get_button(ptrev),
button);
litest_assert_int_eq(libinput_event_pointer_get_button_state(ptrev),
state);
return ptrev;
}
@ -1527,14 +1663,14 @@ litest_is_axis_event(struct libinput_event *event,
struct libinput_event_pointer *ptrev;
enum libinput_event_type type = LIBINPUT_EVENT_POINTER_AXIS;
ck_assert(event != NULL);
ck_assert_int_eq(libinput_event_get_type(event), type);
litest_assert(event != NULL);
litest_assert_int_eq(libinput_event_get_type(event), type);
ptrev = libinput_event_get_pointer_event(event);
ck_assert(libinput_event_pointer_has_axis(ptrev, axis));
litest_assert(libinput_event_pointer_has_axis(ptrev, axis));
if (source != 0)
ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
source);
litest_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
source);
return ptrev;
}
@ -1546,8 +1682,8 @@ litest_is_motion_event(struct libinput_event *event)
enum libinput_event_type type = LIBINPUT_EVENT_POINTER_MOTION;
double x, y, ux, uy;
ck_assert(event != NULL);
ck_assert_int_eq(libinput_event_get_type(event), type);
litest_assert(event != NULL);
litest_assert_int_eq(libinput_event_get_type(event), type);
ptrev = libinput_event_get_pointer_event(event);
x = libinput_event_pointer_get_dx(ptrev);
@ -1556,8 +1692,8 @@ litest_is_motion_event(struct libinput_event *event)
uy = libinput_event_pointer_get_dy_unaccelerated(ptrev);
/* No 0 delta motion events */
ck_assert(x != 0.0 || y != 0.0 ||
ux != 0.0 || uy != 0.0);
litest_assert(x != 0.0 || y != 0.0 ||
ux != 0.0 || uy != 0.0);
return ptrev;
}
@ -1582,7 +1718,7 @@ litest_is_touch_event(struct libinput_event *event,
{
struct libinput_event_touch *touch;
ck_assert(event != NULL);
litest_assert(event != NULL);
if (type == 0)
type = libinput_event_get_type(event);
@ -1592,7 +1728,7 @@ litest_is_touch_event(struct libinput_event *event,
case LIBINPUT_EVENT_TOUCH_UP:
case LIBINPUT_EVENT_TOUCH_MOTION:
case LIBINPUT_EVENT_TOUCH_FRAME:
ck_assert_int_eq(libinput_event_get_type(event), type);
litest_assert_int_eq(libinput_event_get_type(event), type);
break;
default:
ck_abort_msg("%s: invalid touch type %d\n", __func__, type);
@ -1611,15 +1747,15 @@ litest_is_keyboard_event(struct libinput_event *event,
struct libinput_event_keyboard *kevent;
enum libinput_event_type type = LIBINPUT_EVENT_KEYBOARD_KEY;
ck_assert_notnull(event);
ck_assert_int_eq(libinput_event_get_type(event), type);
litest_assert(event != NULL);
litest_assert_int_eq(libinput_event_get_type(event), type);
kevent = libinput_event_get_keyboard_event(event);
ck_assert_notnull(kevent);
litest_assert(kevent != NULL);
ck_assert_int_eq(libinput_event_keyboard_get_key(kevent), key);
ck_assert_int_eq(libinput_event_keyboard_get_key_state(kevent),
state);
litest_assert_int_eq(libinput_event_keyboard_get_key(kevent), key);
litest_assert_int_eq(libinput_event_keyboard_get_key_state(kevent),
state);
return kevent;
}
@ -1634,7 +1770,7 @@ litest_assert_scroll(struct libinput *li,
event = libinput_get_event(li);
next_event = libinput_get_event(li);
ck_assert(next_event != NULL); /* At least 1 scroll + stop scroll */
litest_assert(next_event != NULL); /* At least 1 scroll + stop scroll */
while (event) {
ptrev = litest_is_axis_event(event, axis, 0);
@ -1644,13 +1780,13 @@ litest_assert_scroll(struct libinput *li,
axis);
/* Normal scroll event, check dir */
if (minimum_movement > 0) {
ck_assert_int_ge(value, minimum_movement);
litest_assert_int_ge(value, minimum_movement);
} else {
ck_assert_int_le(value, minimum_movement);
litest_assert_int_le(value, minimum_movement);
}
} else {
/* Last scroll event, must be 0 */
ck_assert_int_eq(
litest_assert_int_eq(
libinput_event_pointer_get_axis_value(ptrev, axis),
0);
}
@ -1670,11 +1806,11 @@ litest_assert_only_typed_events(struct libinput *li,
libinput_dispatch(li);
event = libinput_get_event(li);
ck_assert_notnull(event);
litest_assert_notnull(event);
while (event) {
ck_assert_int_eq(libinput_event_get_type(event),
type);
litest_assert_int_eq(libinput_event_get_type(event),
type);
libinput_event_destroy(event);
libinput_dispatch(li);
event = libinput_get_event(li);

View file

@ -32,6 +32,62 @@
#include <libevdev/libevdev.h>
#include <libevdev/libevdev-uinput.h>
#include <libinput.h>
#include <math.h>
#define litest_assert(cond) \
do { \
if (!(cond)) \
litest_fail_condition(__FILE__, __LINE__, __func__, \
#cond, NULL); \
} while(0)
#define litest_assert_msg(cond, ...) \
do { \
if (!(cond)) \
litest_fail_condition(__FILE__, __LINE__, __func__, \
#cond, __VA_ARGS__); \
} while(0)
#define litest_abort_msg(...) \
litest_fail_condition(__FILE__, __LINE__, __func__, \
"aborting", __VA_ARGS__); \
#define litest_assert_notnull(cond) \
do { \
if ((cond) == NULL) \
litest_fail_condition(__FILE__, __LINE__, __func__, \
#cond, " expected to be not NULL"); \
} while(0)
#define litest_assert_comparison_int_(a_, op_, b_) \
do { \
__typeof__(a_) _a = a_; \
__typeof__(b_) _b = b_; \
if (trunc(_a) != _a || trunc(_b) != _b) \
litest_abort_msg("litest_assert_int_* used for non-integer value\n"); \
if (!((_a) op_ (_b))) \
litest_fail_comparison_int(__FILE__, __LINE__, __func__,\
#op_, _a, _b, \
#a_, #b_); \
} while(0)
#define litest_assert_int_eq(a_, b_) \
litest_assert_comparison_int_(a_, ==, b_)
#define litest_assert_int_ne(a_, b_) \
litest_assert_comparison_int_(a_, !=, b_)
#define litest_assert_int_lt(a_, b_) \
litest_assert_comparison_int_(a_, <, b_)
#define litest_assert_int_le(a_, b_) \
litest_assert_comparison_int_(a_, <=, b_)
#define litest_assert_int_ge(a_, b_) \
litest_assert_comparison_int_(a_, >=, b_)
#define litest_assert_int_gt(a_, b_) \
litest_assert_comparison_int_(a_, >, b_)
enum litest_device_type {
LITEST_NO_DEVICE = -1,
@ -109,6 +165,23 @@ struct libinput *litest_create_context(void);
void litest_disable_log_handler(struct libinput *libinput);
void litest_restore_log_handler(struct libinput *libinput);
void
litest_fail_condition(const char *file,
int line,
const char *func,
const char *condition,
const char *message,
...);
void
litest_fail_comparison_int(const char *file,
int line,
const char *func,
const char *operator,
int a,
int b,
const char *astr,
const char *bstr);
void litest_add(const char *name, void *func,
enum litest_device_feature required_feature,
enum litest_device_feature excluded_feature);

View file

@ -13,3 +13,11 @@
...
fun:mtdev_put_event
}
{
libunwind:msync_uninitialized_bytes
Memcheck:Param
msync(start)
fun:__msync_nocancel
...
fun:litest_backtrace
}