diff --git a/test/Makefile.am b/test/Makefile.am index 49fe5f0f..b9a26f50 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -18,7 +18,14 @@ liblitest_la_SOURCES = \ litest-wacom-touch.c \ litest.c -run_tests = test-udev test-path test-pointer test-touch test-log test-touchpad +run_tests = \ + test-udev \ + test-path \ + test-pointer \ + test-touch \ + test-log \ + test-touchpad \ + test-misc build_tests = \ test-build-cxx \ test-build-linker \ @@ -58,6 +65,11 @@ test_touchpad_CFLAGS = $(AM_CPPFLAGS) test_touchpad_LDADD = $(TEST_LIBS) test_touchpad_LDFLAGS = -static +test_misc_SOURCES = misc.c +test_misc_CFLAGS = $(AM_CPPFLAGS) +test_misc_LDADD = $(TEST_LIBS) +test_misc_LDFLAGS = -static + # build-test only test_build_pedantic_c99_SOURCES = build-pedantic.c test_build_pedantic_c99_CFLAGS = $(TEST_CFLAGS) -std=c99 -pedantic -Werror diff --git a/test/misc.c b/test/misc.c new file mode 100644 index 00000000..5bf94776 --- /dev/null +++ b/test/misc.c @@ -0,0 +1,377 @@ +/* + * Copyright © 2014 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include + +#include "litest.h" + +static int open_restricted(const char *path, int flags, void *data) +{ + int fd = open(path, flags); + return fd < 0 ? -errno : fd; +} +static void close_restricted(int fd, void *data) +{ + close(fd); +} + +const struct libinput_interface simple_interface = { + .open_restricted = open_restricted, + .close_restricted = close_restricted, +}; + +static struct libevdev_uinput * +create_simple_test_device(const char *name, ...) +{ + va_list args; + struct libevdev_uinput *uinput; + struct libevdev *evdev; + unsigned int type, code; + int rc; + struct input_absinfo abs = { + .value = -1, + .minimum = 0, + .maximum = 100, + .fuzz = 0, + .flat = 0, + .resolution = 100, + }; + + evdev = libevdev_new(); + ck_assert(evdev != NULL); + libevdev_set_name(evdev, name); + + va_start(args, name); + + while ((type = va_arg(args, unsigned int)) != -1 && + (code = va_arg(args, unsigned int)) != -1) { + const struct input_absinfo *a = NULL; + if (type == EV_ABS) + a = &abs; + libevdev_enable_event_code(evdev, type, code, a); + } + + va_end(args); + + rc = libevdev_uinput_create_from_device(evdev, + LIBEVDEV_UINPUT_OPEN_MANAGED, + &uinput); + ck_assert_int_eq(rc, 0); + libevdev_free(evdev); + + return uinput; +} + +START_TEST(event_conversion_device_notify) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_event *event; + int device_added = 0, device_removed = 0; + + uinput = create_simple_test_device("test device", + EV_REL, REL_X, + EV_REL, REL_Y, + EV_KEY, BTN_LEFT, + EV_KEY, BTN_MIDDLE, + EV_KEY, BTN_LEFT, + -1, -1); + li = libinput_path_create_context(&simple_interface, NULL); + libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput)); + + libinput_dispatch(li); + libinput_suspend(li); + libinput_resume(li); + + while ((event = libinput_get_event(li))) { + enum libinput_event_type type; + type = libinput_event_get_type(event); + + if (type == LIBINPUT_EVENT_DEVICE_ADDED || + type == LIBINPUT_EVENT_DEVICE_REMOVED) { + struct libinput_event_device_notify *dn; + struct libinput_event *base; + dn = libinput_event_get_device_notify_event(event); + base = libinput_event_device_notify_get_base_event(dn); + ck_assert(event == base); + + if (type == LIBINPUT_EVENT_DEVICE_ADDED) + device_added++; + else if (type == LIBINPUT_EVENT_DEVICE_REMOVED) + device_removed++; + + ck_assert(libinput_event_get_pointer_event(event) == NULL); + ck_assert(libinput_event_get_keyboard_event(event) == NULL); + ck_assert(libinput_event_get_touch_event(event) == NULL); + } + + libinput_event_destroy(event); + } + + libinput_destroy(li); + libevdev_uinput_destroy(uinput); + + ck_assert_int_gt(device_added, 0); + ck_assert_int_gt(device_removed, 0); +} +END_TEST + +START_TEST(event_conversion_pointer) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_event *event; + int motion = 0, button = 0; + + uinput = create_simple_test_device("test device", + EV_REL, REL_X, + EV_REL, REL_Y, + EV_KEY, BTN_LEFT, + EV_KEY, BTN_MIDDLE, + EV_KEY, BTN_LEFT, + -1, -1); + li = libinput_path_create_context(&simple_interface, NULL); + libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput)); + + libevdev_uinput_write_event(uinput, EV_REL, REL_X, -1); + libevdev_uinput_write_event(uinput, EV_REL, REL_Y, -1); + libevdev_uinput_write_event(uinput, EV_KEY, BTN_LEFT, 1); + libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); + + libinput_dispatch(li); + + while ((event = libinput_get_event(li))) { + enum libinput_event_type type; + type = libinput_event_get_type(event); + + if (type == LIBINPUT_EVENT_POINTER_MOTION || + type == LIBINPUT_EVENT_POINTER_BUTTON) { + struct libinput_event_pointer *p; + struct libinput_event *base; + p = libinput_event_get_pointer_event(event); + base = libinput_event_pointer_get_base_event(p); + ck_assert(event == base); + + if (type == LIBINPUT_EVENT_POINTER_MOTION) + motion++; + else if (type == LIBINPUT_EVENT_POINTER_BUTTON) + button++; + + ck_assert(libinput_event_get_device_notify_event(event) == NULL); + ck_assert(libinput_event_get_keyboard_event(event) == NULL); + ck_assert(libinput_event_get_touch_event(event) == NULL); + } + libinput_event_destroy(event); + } + + libinput_destroy(li); + libevdev_uinput_destroy(uinput); + + ck_assert_int_gt(motion, 0); + ck_assert_int_gt(button, 0); +} +END_TEST + +START_TEST(event_conversion_pointer_abs) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_event *event; + int motion = 0, button = 0; + + uinput = create_simple_test_device("test device", + EV_ABS, ABS_X, + EV_ABS, ABS_Y, + EV_KEY, BTN_LEFT, + EV_KEY, BTN_MIDDLE, + EV_KEY, BTN_LEFT, + -1, -1); + li = libinput_path_create_context(&simple_interface, NULL); + libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput)); + libinput_dispatch(li); + + libevdev_uinput_write_event(uinput, EV_ABS, ABS_X, 10); + libevdev_uinput_write_event(uinput, EV_ABS, ABS_Y, 50); + libevdev_uinput_write_event(uinput, EV_KEY, BTN_LEFT, 1); + libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); + libevdev_uinput_write_event(uinput, EV_ABS, ABS_X, 30); + libevdev_uinput_write_event(uinput, EV_ABS, ABS_Y, 30); + libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); + + libinput_dispatch(li); + + while ((event = libinput_get_event(li))) { + enum libinput_event_type type; + type = libinput_event_get_type(event); + + if (type == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE || + type == LIBINPUT_EVENT_POINTER_BUTTON) { + struct libinput_event_pointer *p; + struct libinput_event *base; + p = libinput_event_get_pointer_event(event); + base = libinput_event_pointer_get_base_event(p); + ck_assert(event == base); + + if (type == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE) + motion++; + else if (type == LIBINPUT_EVENT_POINTER_BUTTON) + button++; + + ck_assert(libinput_event_get_device_notify_event(event) == NULL); + ck_assert(libinput_event_get_keyboard_event(event) == NULL); + ck_assert(libinput_event_get_touch_event(event) == NULL); + } + libinput_event_destroy(event); + } + + libinput_destroy(li); + libevdev_uinput_destroy(uinput); + + ck_assert_int_gt(motion, 0); + ck_assert_int_gt(button, 0); +} +END_TEST + +START_TEST(event_conversion_key) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_event *event; + int key = 0; + + uinput = create_simple_test_device("test device", + EV_KEY, KEY_A, + EV_KEY, KEY_B, + -1, -1); + li = libinput_path_create_context(&simple_interface, NULL); + libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput)); + libinput_dispatch(li); + + libevdev_uinput_write_event(uinput, EV_KEY, KEY_A, 1); + libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); + libevdev_uinput_write_event(uinput, EV_KEY, KEY_A, 0); + libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); + + libinput_dispatch(li); + + while ((event = libinput_get_event(li))) { + enum libinput_event_type type; + type = libinput_event_get_type(event); + + if (type == LIBINPUT_EVENT_KEYBOARD_KEY) { + struct libinput_event_keyboard *k; + struct libinput_event *base; + k = libinput_event_get_keyboard_event(event); + base = libinput_event_keyboard_get_base_event(k); + ck_assert(event == base); + + key++; + + ck_assert(libinput_event_get_device_notify_event(event) == NULL); + ck_assert(libinput_event_get_pointer_event(event) == NULL); + ck_assert(libinput_event_get_touch_event(event) == NULL); + } + libinput_event_destroy(event); + } + + libinput_destroy(li); + libevdev_uinput_destroy(uinput); + + ck_assert_int_gt(key, 0); +} +END_TEST + +START_TEST(event_conversion_touch) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_event *event; + int touch = 0; + + uinput = create_simple_test_device("test device", + EV_KEY, BTN_TOUCH, + EV_ABS, ABS_X, + EV_ABS, ABS_Y, + EV_ABS, ABS_MT_SLOT, + EV_ABS, ABS_MT_TRACKING_ID, + EV_ABS, ABS_MT_POSITION_X, + EV_ABS, ABS_MT_POSITION_Y, + -1, -1); + li = libinput_path_create_context(&simple_interface, NULL); + libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput)); + libinput_dispatch(li); + + libevdev_uinput_write_event(uinput, EV_KEY, BTN_TOOL_FINGER, 1); + libevdev_uinput_write_event(uinput, EV_KEY, BTN_TOUCH, 1); + libevdev_uinput_write_event(uinput, EV_ABS, ABS_X, 10); + libevdev_uinput_write_event(uinput, EV_ABS, ABS_Y, 10); + libevdev_uinput_write_event(uinput, EV_ABS, ABS_MT_SLOT, 0); + libevdev_uinput_write_event(uinput, EV_ABS, ABS_MT_TRACKING_ID, 1); + libevdev_uinput_write_event(uinput, EV_ABS, ABS_MT_POSITION_X, 10); + libevdev_uinput_write_event(uinput, EV_ABS, ABS_MT_POSITION_Y, 10); + libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); + + libinput_dispatch(li); + + while ((event = libinput_get_event(li))) { + enum libinput_event_type type; + type = libinput_event_get_type(event); + + if (type >= LIBINPUT_EVENT_TOUCH_DOWN && + type <= LIBINPUT_EVENT_TOUCH_FRAME) { + struct libinput_event_touch *t; + struct libinput_event *base; + t = libinput_event_get_touch_event(event); + base = libinput_event_touch_get_base_event(t); + ck_assert(event == base); + + touch++; + + ck_assert(libinput_event_get_device_notify_event(event) == NULL); + ck_assert(libinput_event_get_pointer_event(event) == NULL); + ck_assert(libinput_event_get_keyboard_event(event) == NULL); + } + libinput_event_destroy(event); + } + + libinput_destroy(li); + libevdev_uinput_destroy(uinput); + + ck_assert_int_gt(touch, 0); +} +END_TEST + +int main (int argc, char **argv) { + litest_add_no_device("events:conversion", event_conversion_device_notify); + litest_add_no_device("events:conversion", event_conversion_pointer); + litest_add_no_device("events:conversion", event_conversion_pointer_abs); + litest_add_no_device("events:conversion", event_conversion_key); + litest_add_no_device("events:conversion", event_conversion_touch); + + return litest_run(argc, argv); +}