2 * Copyright © 2013 Red Hat, Inc.
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
37 #include "linux/input.h"
38 #include <sys/ptrace.h>
39 #include <sys/timerfd.h>
43 #include "litest-int.h"
44 #include "libinput-util.h"
46 static int in_debugger = -1;
47 static int verbose = 0;
53 enum litest_device_type devices;
63 static struct litest_device *current_device;
65 struct litest_device *litest_current_device(void) {
66 return current_device;
69 void litest_set_current_device(struct litest_device *device) {
70 current_device = device;
73 void litest_generic_device_teardown(void)
75 litest_delete_device(current_device);
76 current_device = NULL;
79 extern struct litest_test_device litest_keyboard_device;
80 extern struct litest_test_device litest_synaptics_clickpad_device;
81 extern struct litest_test_device litest_synaptics_touchpad_device;
82 extern struct litest_test_device litest_synaptics_t440_device;
83 extern struct litest_test_device litest_trackpoint_device;
84 extern struct litest_test_device litest_bcm5974_device;
85 extern struct litest_test_device litest_mouse_device;
86 extern struct litest_test_device litest_wacom_touch_device;
88 struct litest_test_device* devices[] = {
89 &litest_synaptics_clickpad_device,
90 &litest_synaptics_touchpad_device,
91 &litest_synaptics_t440_device,
92 &litest_keyboard_device,
93 &litest_trackpoint_device,
94 &litest_bcm5974_device,
96 &litest_wacom_touch_device,
100 static struct list all_tests;
103 litest_add_tcase_for_device(struct suite *suite,
105 const struct litest_test_device *dev)
108 const char *test_name = dev->shortname;
110 list_for_each(t, &suite->tests, node) {
111 if (strcmp(t->name, test_name) != 0)
114 tcase_add_test(t->tc, func);
118 t = zalloc(sizeof(*t));
119 t->name = strdup(test_name);
120 t->tc = tcase_create(test_name);
121 list_insert(&suite->tests, &t->node);
122 tcase_add_checked_fixture(t->tc, dev->setup,
123 dev->teardown ? dev->teardown : litest_generic_device_teardown);
124 tcase_add_test(t->tc, func);
125 suite_add_tcase(suite->suite, t->tc);
129 litest_add_tcase_no_device(struct suite *suite, void *func)
132 const char *test_name = "no device";
134 list_for_each(t, &suite->tests, node) {
135 if (strcmp(t->name, test_name) != 0)
138 tcase_add_test(t->tc, func);
142 t = zalloc(sizeof(*t));
143 t->name = strdup(test_name);
144 t->tc = tcase_create(test_name);
145 list_insert(&suite->tests, &t->node);
146 tcase_add_test(t->tc, func);
147 suite_add_tcase(suite->suite, t->tc);
151 litest_add_tcase(struct suite *suite, void *func,
152 enum litest_device_feature required,
153 enum litest_device_feature excluded)
155 struct litest_test_device **dev = devices;
157 if (required == LITEST_DISABLE_DEVICE &&
158 excluded == LITEST_DISABLE_DEVICE) {
159 litest_add_tcase_no_device(suite, func);
160 } else if (required != LITEST_ANY || excluded != LITEST_ANY) {
162 if (((*dev)->features & required) == required &&
163 ((*dev)->features & excluded) == 0)
164 litest_add_tcase_for_device(suite, func, *dev);
169 litest_add_tcase_for_device(suite, func, *dev);
176 litest_add_no_device(const char *name, void *func)
178 litest_add(name, func, LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE);
182 litest_add(const char *name,
184 enum litest_device_feature required,
185 enum litest_device_feature excluded)
189 if (all_tests.next == NULL && all_tests.prev == NULL)
190 list_init(&all_tests);
192 list_for_each(s, &all_tests, node) {
193 if (strcmp(s->name, name) == 0) {
194 litest_add_tcase(s, func, required, excluded);
199 s = zalloc(sizeof(*s));
200 s->name = strdup(name);
201 s->suite = suite_create(s->name);
203 list_init(&s->tests);
204 list_insert(&all_tests, &s->node);
205 litest_add_tcase(s, func, required, excluded);
209 is_debugger_attached(void)
219 int ppid = getppid();
220 if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) == 0) {
221 waitpid(ppid, NULL, 0);
222 ptrace(PTRACE_CONT, NULL, NULL);
223 ptrace(PTRACE_DETACH, ppid, NULL, NULL);
230 waitpid(pid, &status, 0);
231 rc = WEXITSTATUS(status);
238 litest_list_tests(struct list *tests)
242 list_for_each(s, tests, node) {
244 printf("%s:\n", s->name);
245 list_for_each(t, &s->tests, node) {
246 printf(" %s\n", t->name);
252 litest_log_handler(struct libinput *libinput,
253 enum libinput_log_priority pri,
257 const char *priority = NULL;
260 case LIBINPUT_LOG_PRIORITY_INFO: priority = "info"; break;
261 case LIBINPUT_LOG_PRIORITY_ERROR: priority = "error"; break;
262 case LIBINPUT_LOG_PRIORITY_DEBUG: priority = "debug"; break;
265 fprintf(stderr, "litest %s: ", priority);
266 vfprintf(stderr, format, args);
270 open_restricted(const char *path, int flags, void *userdata)
272 return open(path, flags);
276 close_restricted(int fd, void *userdata)
281 struct libinput_interface interface = {
282 .open_restricted = open_restricted,
283 .close_restricted = close_restricted,
286 static const struct option opts[] = {
287 { "list", 0, 0, 'l' },
288 { "verbose", 0, 0, 'v' },
293 litest_run(int argc, char **argv) {
294 struct suite *s, *snext;
298 if (in_debugger == -1) {
299 in_debugger = is_debugger_attached();
301 setenv("CK_FORK", "no", 0);
304 list_for_each(s, &all_tests, node) {
306 sr = srunner_create(s->suite);
308 srunner_add_suite(sr, s->suite);
313 int option_index = 0;
315 c = getopt_long(argc, argv, "", opts, &option_index);
320 litest_list_tests(&all_tests);
326 fprintf(stderr, "usage: %s [--list]\n", argv[0]);
332 srunner_run_all(sr, CK_NORMAL);
333 failed = srunner_ntests_failed(sr);
336 list_for_each_safe(s, snext, &all_tests, node) {
337 struct test *t, *tnext;
339 list_for_each_safe(t, tnext, &s->tests, node) {
341 list_remove(&t->node);
345 list_remove(&s->node);
353 static struct input_absinfo *
354 merge_absinfo(const struct input_absinfo *orig,
355 const struct input_absinfo *override)
357 struct input_absinfo *abs;
358 unsigned int nelem, i;
359 size_t sz = ABS_MAX + 1;
364 abs = calloc(sz, sizeof(*abs));
365 ck_assert(abs != NULL);
368 while (orig[nelem].value != -1) {
369 abs[nelem] = orig[nelem];
371 ck_assert_int_lt(nelem, sz);
374 /* just append, if the same axis is present twice, libevdev will
375 only use the last value anyway */
377 while (override && override[i].value != -1) {
378 abs[nelem++] = override[i++];
379 ck_assert_int_lt(nelem, sz);
382 ck_assert_int_lt(nelem, sz);
383 abs[nelem].value = -1;
389 merge_events(const int *orig, const int *override)
392 unsigned int nelem, i;
393 size_t sz = KEY_MAX * 3;
398 events = calloc(sz, sizeof(int));
399 ck_assert(events != NULL);
402 while (orig[nelem] != -1) {
403 events[nelem] = orig[nelem];
405 ck_assert_int_lt(nelem, sz);
408 /* just append, if the same axis is present twice, libevdev will
409 * ignore the double definition anyway */
411 while (override && override[i] != -1) {
412 events[nelem++] = override[i++];
413 ck_assert_int_le(nelem, sz);
416 ck_assert_int_lt(nelem, sz);
422 static struct litest_device *
423 litest_create(enum litest_device_type which,
424 const char *name_override,
425 struct input_id *id_override,
426 const struct input_absinfo *abs_override,
427 const int *events_override)
429 struct litest_device *d = NULL;
430 struct litest_test_device **dev;
432 const struct input_id *id;
433 struct input_absinfo *abs;
438 if ((*dev)->type == which)
444 ck_abort_msg("Invalid device type %d\n", which);
446 d = zalloc(sizeof(*d));
447 ck_assert(d != NULL);
449 /* device has custom create method */
450 if ((*dev)->create) {
452 if (abs_override || events_override)
453 ck_abort_msg("Custom create cannot"
459 abs = merge_absinfo((*dev)->absinfo, abs_override);
460 events = merge_events((*dev)->events, events_override);
461 name = name_override ? name_override : (*dev)->name;
462 id = id_override ? id_override : (*dev)->id;
464 d->uinput = litest_create_uinput_device_from_description(name,
468 d->interface = (*dev)->interface;
477 litest_create_context(void)
479 struct libinput *libinput =
480 libinput_path_create_context(&interface, NULL);
481 ck_assert_notnull(libinput);
483 libinput_log_set_handler(libinput, litest_log_handler);
485 libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
490 struct litest_device *
491 litest_add_device_with_overrides(struct libinput *libinput,
492 enum litest_device_type which,
493 const char *name_override,
494 struct input_id *id_override,
495 const struct input_absinfo *abs_override,
496 const int *events_override)
498 struct litest_device *d;
503 d = litest_create(which,
509 path = libevdev_uinput_get_devnode(d->uinput);
510 ck_assert(path != NULL);
511 fd = open(path, O_RDWR|O_NONBLOCK);
512 ck_assert_int_ne(fd, -1);
514 rc = libevdev_new_from_fd(fd, &d->evdev);
515 ck_assert_int_eq(rc, 0);
517 d->libinput = libinput;
518 d->libinput_device = libinput_path_add_device(d->libinput, path);
519 ck_assert(d->libinput_device != NULL);
520 libinput_device_ref(d->libinput_device);
523 d->interface->min[ABS_X] = libevdev_get_abs_minimum(d->evdev, ABS_X);
524 d->interface->max[ABS_X] = libevdev_get_abs_maximum(d->evdev, ABS_X);
525 d->interface->min[ABS_Y] = libevdev_get_abs_minimum(d->evdev, ABS_Y);
526 d->interface->max[ABS_Y] = libevdev_get_abs_maximum(d->evdev, ABS_Y);
531 struct litest_device *
532 litest_create_device_with_overrides(enum litest_device_type which,
533 const char *name_override,
534 struct input_id *id_override,
535 const struct input_absinfo *abs_override,
536 const int *events_override)
538 struct litest_device *dev =
539 litest_add_device_with_overrides(litest_create_context(),
545 dev->owns_context = true;
549 struct litest_device *
550 litest_create_device(enum litest_device_type which)
552 return litest_create_device_with_overrides(which, NULL, NULL, NULL, NULL);
556 litest_handle_events(struct litest_device *d)
560 fd.fd = libinput_get_fd(d->libinput);
563 while (poll(&fd, 1, 1))
564 libinput_dispatch(d->libinput);
570 litest_delete_device(struct litest_device *d)
575 libinput_device_unref(d->libinput_device);
577 libinput_unref(d->libinput);
578 libevdev_free(d->evdev);
579 libevdev_uinput_destroy(d->uinput);
580 memset(d,0, sizeof(*d));
585 litest_event(struct litest_device *d, unsigned int type,
586 unsigned int code, int value)
588 int ret = libevdev_uinput_write_event(d->uinput, type, code, value);
589 ck_assert_int_eq(ret, 0);
593 auto_assign_value(struct litest_device *d,
594 const struct input_event *ev,
595 int slot, double x, double y)
597 static int tracking_id;
598 int value = ev->value;
600 if (value != LITEST_AUTO_ASSIGN || ev->type != EV_ABS)
605 case ABS_MT_POSITION_X:
606 value = litest_scale(d, ABS_X, x);
609 case ABS_MT_POSITION_Y:
610 value = litest_scale(d, ABS_Y, y);
612 case ABS_MT_TRACKING_ID:
613 value = ++tracking_id;
625 litest_touch_down(struct litest_device *d, unsigned int slot,
628 struct input_event *ev;
630 if (d->interface->touch_down) {
631 d->interface->touch_down(d, slot, x, y);
635 ev = d->interface->touch_down_events;
636 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
637 int value = auto_assign_value(d, ev, slot, x, y);
638 litest_event(d, ev->type, ev->code, value);
644 litest_touch_up(struct litest_device *d, unsigned int slot)
646 struct input_event *ev;
647 struct input_event up[] = {
648 { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
649 { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
650 { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
651 { .type = -1, .code = -1 }
654 if (d->interface->touch_up) {
655 d->interface->touch_up(d, slot);
657 } else if (d->interface->touch_up_events) {
658 ev = d->interface->touch_up_events;
662 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
663 int value = auto_assign_value(d, ev, slot, 0, 0);
664 litest_event(d, ev->type, ev->code, value);
670 litest_touch_move(struct litest_device *d, unsigned int slot,
673 struct input_event *ev;
675 if (d->interface->touch_move) {
676 d->interface->touch_move(d, slot, x, y);
680 ev = d->interface->touch_move_events;
681 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
682 int value = auto_assign_value(d, ev, slot, x, y);
683 litest_event(d, ev->type, ev->code, value);
689 litest_touch_move_to(struct litest_device *d,
691 double x_from, double y_from,
692 double x_to, double y_to,
695 for (int i = 0; i < steps - 1; i++)
696 litest_touch_move(d, slot,
697 x_from + (x_to - x_from)/steps * i,
698 y_from + (y_to - y_from)/steps * i);
699 litest_touch_move(d, slot, x_to, y_to);
703 litest_button_click(struct litest_device *d, unsigned int button, bool is_press)
706 struct input_event *ev;
707 struct input_event click[] = {
708 { .type = EV_KEY, .code = button, .value = is_press ? 1 : 0 },
709 { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
712 ARRAY_FOR_EACH(click, ev)
713 litest_event(d, ev->type, ev->code, ev->value);
717 litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press)
719 litest_button_click(d, key, is_press);
723 litest_scale(const struct litest_device *d, unsigned int axis, double val)
726 ck_assert_int_ge(val, 0);
727 ck_assert_int_le(val, 100);
728 ck_assert_int_le(axis, ABS_Y);
730 min = d->interface->min[axis];
731 max = d->interface->max[axis];
732 return (max - min) * val/100.0 + min;
736 litest_drain_events(struct libinput *li)
738 struct libinput_event *event;
740 libinput_dispatch(li);
741 while ((event = libinput_get_event(li))) {
742 libinput_event_destroy(event);
743 libinput_dispatch(li);
748 litest_print_event(struct libinput_event *event)
750 struct libinput_event_pointer *p;
751 struct libinput_device *dev;
752 enum libinput_event_type type;
755 dev = libinput_event_get_device(event);
756 type = libinput_event_get_type(event);
759 "device %s type %d ",
760 libinput_device_get_sysname(dev),
763 case LIBINPUT_EVENT_POINTER_MOTION:
764 p = libinput_event_get_pointer_event(event);
765 x = libinput_event_pointer_get_dx(p);
766 y = libinput_event_pointer_get_dy(p);
767 fprintf(stderr, "motion: %.2f/%.2f", x, y);
769 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
770 p = libinput_event_get_pointer_event(event);
771 x = libinput_event_pointer_get_absolute_x(p);
772 y = libinput_event_pointer_get_absolute_y(p);
773 fprintf(stderr, "motion: %.2f/%.2f", x, y);
775 case LIBINPUT_EVENT_POINTER_BUTTON:
776 p = libinput_event_get_pointer_event(event);
778 "button: %d state %d",
779 libinput_event_pointer_get_button(p),
780 libinput_event_pointer_get_button_state(p));
786 fprintf(stderr, "\n");
790 litest_assert_empty_queue(struct libinput *li)
792 bool empty_queue = true;
793 struct libinput_event *event;
795 libinput_dispatch(li);
796 while ((event = libinput_get_event(li))) {
799 "Unexpected event: ");
800 litest_print_event(event);
801 libinput_event_destroy(event);
802 libinput_dispatch(li);
805 ck_assert(empty_queue);
808 struct libevdev_uinput *
809 litest_create_uinput_device_from_description(const char *name,
810 const struct input_id *id,
811 const struct input_absinfo *abs_info,
814 struct libevdev_uinput *uinput;
815 struct libevdev *dev;
818 const struct input_absinfo *abs;
819 const struct input_absinfo default_abs = {
830 dev = libevdev_new();
831 ck_assert(dev != NULL);
833 snprintf(buf, sizeof(buf), "litest %s", name);
834 libevdev_set_name(dev, buf);
836 libevdev_set_id_bustype(dev, id->bustype);
837 libevdev_set_id_vendor(dev, id->vendor);
838 libevdev_set_id_product(dev, id->product);
842 while (abs && abs->value != -1) {
843 rc = libevdev_enable_event_code(dev, EV_ABS,
845 ck_assert_int_eq(rc, 0);
850 (type = *events++) != -1 &&
851 (code = *events++) != -1) {
852 if (type == INPUT_PROP_MAX) {
853 rc = libevdev_enable_property(dev, code);
856 ck_assert(!libevdev_has_event_code(dev, type, code));
857 rc = libevdev_enable_event_code(dev, type, code,
858 type == EV_ABS ? &default_abs : NULL);
860 ck_assert_int_eq(rc, 0);
863 rc = libevdev_uinput_create_from_device(dev,
864 LIBEVDEV_UINPUT_OPEN_MANAGED,
866 ck_assert_int_eq(rc, 0);
870 /* uinput does not yet support setting the resolution, so we set it
871 * afterwards. This is of course racy as hell but the way we
872 * _generally_ use this function by the time libinput uses the
873 * device, we're finished here */
875 devnode = libevdev_uinput_get_devnode(uinput);
876 ck_assert_notnull(devnode);
877 fd = open(devnode, O_RDONLY);
878 ck_assert_int_gt(fd, -1);
879 rc = libevdev_new_from_fd(fd, &dev);
880 ck_assert_int_eq(rc, 0);
883 while (abs && abs->value != -1) {
884 if (abs->resolution != 0) {
885 rc = libevdev_kernel_set_abs_info(dev,
888 ck_assert_int_eq(rc, 0);
898 static struct libevdev_uinput *
899 litest_create_uinput_abs_device_v(const char *name,
901 const struct input_absinfo *abs,
904 int events[KEY_MAX * 2 + 2]; /* increase this if not sufficient */
908 while ((type = va_arg(args, int)) != -1 &&
909 (code = va_arg(args, int)) != -1) {
912 ck_assert(event < &events[ARRAY_LENGTH(events) - 2]);
918 return litest_create_uinput_device_from_description(name, id,
922 struct libevdev_uinput *
923 litest_create_uinput_abs_device(const char *name,
925 const struct input_absinfo *abs,
928 struct libevdev_uinput *uinput;
932 uinput = litest_create_uinput_abs_device_v(name, id, abs, args);
938 struct libevdev_uinput *
939 litest_create_uinput_device(const char *name, struct input_id *id, ...)
941 struct libevdev_uinput *uinput;
945 uinput = litest_create_uinput_abs_device_v(name, id, NULL, args);