1 /*
2 * Copyright © 2013 Red Hat, Inc.
3 * Copyright © 2013 Marcin Slusarz <marcin.slusarz@gmail.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 #include "config.h"
26
27 #include <check.h>
28 #include <dirent.h>
29 #include <errno.h>
30 #include <libgen.h>
31 #include <fcntl.h>
32 #include <fnmatch.h>
33 #include <getopt.h>
34 #include <poll.h>
35 #include <signal.h>
36 #include <stdint.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stdarg.h>
40 #include <time.h>
41 #include <unistd.h>
42 #include "linux/input.h"
43 #include <sys/ptrace.h>
44 #include <sys/resource.h>
45 #include <sys/timerfd.h>
46 #include <sys/wait.h>
47 #include <sys/stat.h>
48 #include <sys/types.h>
49 #include <sys/sysinfo.h>
50 #include <libudev.h>
51 #if HAVE_LIBSYSTEMD
52 #include <systemd/sd-bus.h>
53 #endif
54 #ifdef __FreeBSD__
55 #include <termios.h>
56 #endif
57
58 #include <valgrind/valgrind.h>
59
60 #include "litest.h"
61 #include "litest-int.h"
62 #include "libinput-util.h"
63 #include "quirks.h"
64 #include "builddir.h"
65
66 #include <linux/kd.h>
67
68 #define UDEV_RULES_D "/run/udev/rules.d"
69 #define UDEV_FUZZ_OVERRIDE_RULE_FILE UDEV_RULES_D \
70 "/91-litest-fuzz-override-REMOVEME-XXXXXX.rules"
71 #define UDEV_TEST_DEVICE_RULE_FILE UDEV_RULES_D \
72 "/91-litest-test-device-REMOVEME-XXXXXXX.rules"
73 #define UDEV_DEVICE_GROUPS_FILE UDEV_RULES_D \
74 "/80-libinput-device-groups-litest-XXXXXX.rules"
75
76 static int jobs;
77 static bool in_debugger = false;
78 static bool verbose = false;
79 static bool run_deviceless = false;
80 static bool use_system_rules_quirks = false;
81 const char *filter_test = NULL;
82 const char *filter_device = NULL;
83 const char *filter_group = NULL;
84 const char *xml_prefix = NULL;
85 static struct quirks_context *quirks_context;
86
87 struct created_file {
88 struct list link;
89 char *path;
90 };
91
92 struct list created_files_list; /* list of all files to remove at the end of
93 the test run */
94
95 static void litest_init_udev_rules(struct list *created_files_list);
96 static void litest_remove_udev_rules(struct list *created_files_list);
97
98 enum quirks_setup_mode {
99 QUIRKS_SETUP_USE_SRCDIR,
100 QUIRKS_SETUP_ONLY_DEVICE,
101 QUIRKS_SETUP_FULL,
102 };
103 static void litest_setup_quirks(struct list *created_files_list,
104 enum quirks_setup_mode mode);
105
106 /* defined for the litest selftest */
107 #ifndef LITEST_DISABLE_BACKTRACE_LOGGING
108 #define litest_log(...) fprintf(stderr, __VA_ARGS__)
109 #define litest_vlog(format_, args_) vfprintf(stderr, format_, args_)
110 #else
111 #define litest_log(...) { /* __VA_ARGS__ */ }
112 #define litest_vlog(...) { /* __VA_ARGS__ */ }
113 #endif
114
115 static void
litest_backtrace(void)116 litest_backtrace(void)
117 {
118 #if HAVE_GSTACK
119 pid_t parent, child;
120 int pipefd[2];
121
122 if (RUNNING_ON_VALGRIND) {
123 litest_log(" Using valgrind, omitting backtrace\n");
124 return;
125 }
126
127 if (pipe(pipefd) == -1)
128 return;
129
130 parent = getpid();
131 child = fork();
132
133 if (child == 0) {
134 char pid[8];
135
136 close(pipefd[0]);
137 dup2(pipefd[1], STDOUT_FILENO);
138
139 sprintf(pid, "%d", parent);
140
141 execlp("gstack", "gstack", pid, NULL);
142 exit(errno);
143 }
144
145 /* parent */
146 char buf[1024];
147 int status, nread;
148
149 close(pipefd[1]);
150 waitpid(child, &status, 0);
151
152 status = WEXITSTATUS(status);
153 if (status != 0) {
154 litest_log("ERROR: gstack failed, no backtrace available: %s\n",
155 strerror(status));
156 } else {
157 litest_log("\nBacktrace:\n");
158 while ((nread = read(pipefd[0], buf, sizeof(buf) - 1)) > 0) {
159 buf[nread] = '\0';
160 litest_log("%s", buf);
161 }
162 litest_log("\n");
163 }
164 close(pipefd[0]);
165 #endif
166 }
167
168 LIBINPUT_ATTRIBUTE_PRINTF(5, 6)
169 __attribute__((noreturn))
170 void
litest_fail_condition(const char * file,int line,const char * func,const char * condition,const char * message,...)171 litest_fail_condition(const char *file,
172 int line,
173 const char *func,
174 const char *condition,
175 const char *message,
176 ...)
177 {
178 litest_log("FAILED: %s\n", condition);
179
180 if (message) {
181 va_list args;
182 va_start(args, message);
183 litest_vlog(message, args);
184 va_end(args);
185 }
186
187 litest_log("in %s() (%s:%d)\n", func, file, line);
188 litest_backtrace();
189 abort();
190 }
191
192 __attribute__((noreturn))
193 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)194 litest_fail_comparison_int(const char *file,
195 int line,
196 const char *func,
197 const char *operator,
198 int a,
199 int b,
200 const char *astr,
201 const char *bstr)
202 {
203 litest_log("FAILED COMPARISON: %s %s %s\n", astr, operator, bstr);
204 litest_log("Resolved to: %d %s %d\n", a, operator, b);
205 litest_log("in %s() (%s:%d)\n", func, file, line);
206 litest_backtrace();
207 abort();
208 }
209
210 __attribute__((noreturn))
211 void
litest_fail_comparison_double(const char * file,int line,const char * func,const char * operator,double a,double b,const char * astr,const char * bstr)212 litest_fail_comparison_double(const char *file,
213 int line,
214 const char *func,
215 const char *operator,
216 double a,
217 double b,
218 const char *astr,
219 const char *bstr)
220 {
221 litest_log("FAILED COMPARISON: %s %s %s\n", astr, operator, bstr);
222 litest_log("Resolved to: %.3f %s %.3f\n", a, operator, b);
223 litest_log("in %s() (%s:%d)\n", func, file, line);
224 litest_backtrace();
225 abort();
226 }
227
228 __attribute__((noreturn))
229 void
litest_fail_comparison_ptr(const char * file,int line,const char * func,const char * comparison)230 litest_fail_comparison_ptr(const char *file,
231 int line,
232 const char *func,
233 const char *comparison)
234 {
235 litest_log("FAILED COMPARISON: %s\n", comparison);
236 litest_log("in %s() (%s:%d)\n", func, file, line);
237 litest_backtrace();
238 abort();
239 }
240
241 struct test {
242 struct list node;
243 char *name;
244 char *devname;
245 const void *func;
246 void *setup;
247 void *teardown;
248
249 struct range range;
250 bool deviceless;
251 };
252
253 struct suite {
254 struct list node;
255 struct list tests;
256 char *name;
257 };
258
259 static struct litest_device *current_device;
260
litest_current_device(void)261 struct litest_device *litest_current_device(void)
262 {
263 return current_device;
264 }
265
266 static void
grab_device(struct litest_device * device,bool mode)267 grab_device(struct litest_device *device, bool mode)
268 {
269 struct libinput *li = libinput_device_get_context(device->libinput_device);
270 struct litest_context *ctx = libinput_get_user_data(li);
271 struct udev_device *udev_device;
272 const char *devnode;
273 struct path *p;
274
275 udev_device = libinput_device_get_udev_device(device->libinput_device);
276 litest_assert_ptr_notnull(udev_device);
277
278 devnode = udev_device_get_devnode(udev_device);
279
280 /* Note: in some tests we create multiple devices for the same path.
281 * This will only grab the first device in the list but we're using
282 * list_insert() so the first device is the latest that was
283 * initialized, so we should be good.
284 */
285 list_for_each(p, &ctx->paths, link) {
286 if (streq(p->path, devnode)) {
287 int rc = ioctl(p->fd, EVIOCGRAB, (void*)mode ? 1 : 0);
288 ck_assert_int_gt(rc, -1);
289 udev_device_unref(udev_device);
290 return;
291 }
292 }
293 litest_abort_msg("Failed to find device %s to %sgrab\n",
294 devnode, mode ? "" : "un");
295 }
296
297 void
litest_grab_device(struct litest_device * device)298 litest_grab_device(struct litest_device *device)
299 {
300 grab_device(device, true);
301 }
302
303 void
litest_ungrab_device(struct litest_device * device)304 litest_ungrab_device(struct litest_device *device)
305 {
306 grab_device(device, false);
307 }
308
litest_set_current_device(struct litest_device * device)309 void litest_set_current_device(struct litest_device *device)
310 {
311 current_device = device;
312 }
313
litest_generic_device_teardown(void)314 void litest_generic_device_teardown(void)
315 {
316 litest_delete_device(current_device);
317 current_device = NULL;
318 }
319
320 struct list devices;
321
322 static struct list all_tests;
323
324 static inline void
litest_system(const char * command)325 litest_system(const char *command)
326 {
327 int ret;
328
329 ret = system(command);
330
331 if (ret == -1) {
332 litest_abort_msg("Failed to execute: %s", command);
333 } else if (WIFEXITED(ret)) {
334 if (WEXITSTATUS(ret))
335 litest_abort_msg("'%s' failed with %d",
336 command,
337 WEXITSTATUS(ret));
338 } else if (WIFSIGNALED(ret)) {
339 litest_abort_msg("'%s' terminated with signal %d",
340 command,
341 WTERMSIG(ret));
342 }
343 }
344
345 static void
litest_reload_udev_rules(void)346 litest_reload_udev_rules(void)
347 {
348 litest_system("udevadm control --reload-rules");
349 }
350
351 static void
litest_add_tcase_for_device(struct suite * suite,const char * funcname,const void * func,const struct litest_test_device * dev,const struct range * range)352 litest_add_tcase_for_device(struct suite *suite,
353 const char *funcname,
354 const void *func,
355 const struct litest_test_device *dev,
356 const struct range *range)
357 {
358 struct test *t;
359
360 t = zalloc(sizeof(*t));
361 t->name = safe_strdup(funcname);
362 t->devname = safe_strdup(dev->shortname);
363 t->func = func;
364 t->setup = dev->setup;
365 t->teardown = dev->teardown ?
366 dev->teardown : litest_generic_device_teardown;
367 if (range)
368 t->range = *range;
369
370 list_insert(&suite->tests, &t->node);
371 }
372
373 static void
litest_add_tcase_no_device(struct suite * suite,const void * func,const char * funcname,const struct range * range)374 litest_add_tcase_no_device(struct suite *suite,
375 const void *func,
376 const char *funcname,
377 const struct range *range)
378 {
379 struct test *t;
380 const char *test_name = funcname;
381
382 if (filter_device &&
383 strstr(test_name, filter_device) == NULL &&
384 fnmatch(filter_device, test_name, 0) != 0)
385 return;
386
387 t = zalloc(sizeof(*t));
388 t->name = safe_strdup(test_name);
389 t->devname = safe_strdup("no device");
390 t->func = func;
391 if (range)
392 t->range = *range;
393 t->setup = NULL;
394 t->teardown = NULL;
395
396 list_insert(&suite->tests, &t->node);
397 }
398
399 static void
litest_add_tcase_deviceless(struct suite * suite,const void * func,const char * funcname,const struct range * range)400 litest_add_tcase_deviceless(struct suite *suite,
401 const void *func,
402 const char *funcname,
403 const struct range *range)
404 {
405 struct test *t;
406 const char *test_name = funcname;
407
408 if (filter_device &&
409 strstr(test_name, filter_device) == NULL &&
410 fnmatch(filter_device, test_name, 0) != 0)
411 return;
412
413 t = zalloc(sizeof(*t));
414 t->deviceless = true;
415 t->name = safe_strdup(test_name);
416 t->devname = safe_strdup("deviceless");
417 t->func = func;
418 if (range)
419 t->range = *range;
420 t->setup = NULL;
421 t->teardown = NULL;
422
423 list_insert(&suite->tests, &t->node);
424 }
425
426 static struct suite *
get_suite(const char * name)427 get_suite(const char *name)
428 {
429 struct suite *s;
430 /* this is the list meson calls, ensure we don't miss out on tests */
431 const char * allowed_suites[] = {
432 "config:", "context:", "device:", "events:", "gestures:",
433 "keyboard:", "lid:", "log:", "misc:", "pad:", "path:",
434 "pointer:", "quirks:", "switch:", "tablet:", "tablet-mode:",
435 "tap:", "timer:", "totem:", "touch:", "touchpad:",
436 "trackball:", "trackpoint:", "udev:",
437 };
438 const char **allowed;
439 bool found = false;
440
441 ARRAY_FOR_EACH(allowed_suites, allowed) {
442 if (strstartswith(name, *allowed)) {
443 found = true;
444 break;
445 }
446 }
447 if (!found)
448 litest_abort_msg("Suite name '%s' is not allowed\n", name);
449
450 list_for_each(s, &all_tests, node) {
451 if (streq(s->name, name))
452 return s;
453 }
454
455 s = zalloc(sizeof(*s));
456 s->name = safe_strdup(name);
457
458 list_init(&s->tests);
459 list_insert(&all_tests, &s->node);
460
461 return s;
462 }
463
464 static void
litest_add_tcase(const char * suite_name,const char * funcname,const void * func,int64_t required,int64_t excluded,const struct range * range)465 litest_add_tcase(const char *suite_name,
466 const char *funcname,
467 const void *func,
468 int64_t required,
469 int64_t excluded,
470 const struct range *range)
471 {
472 struct suite *suite;
473 bool added = false;
474
475 litest_assert(required >= LITEST_DEVICELESS);
476 litest_assert(excluded >= LITEST_DEVICELESS);
477
478 if (filter_test &&
479 strstr(funcname, filter_test) == NULL &&
480 fnmatch(filter_test, funcname, 0) != 0)
481 return;
482
483 if (filter_group &&
484 strstr(suite_name, filter_group) == NULL &&
485 fnmatch(filter_group, suite_name, 0) != 0)
486 return;
487
488 suite = get_suite(suite_name);
489
490 if (required == LITEST_DEVICELESS &&
491 excluded == LITEST_DEVICELESS) {
492 litest_add_tcase_deviceless(suite, func, funcname, range);
493 added = true;
494 } else if (required == LITEST_DISABLE_DEVICE &&
495 excluded == LITEST_DISABLE_DEVICE) {
496 litest_add_tcase_no_device(suite, func, funcname, range);
497 added = true;
498 } else if (required != LITEST_ANY || excluded != LITEST_ANY) {
499 struct litest_test_device *dev;
500
501 list_for_each(dev, &devices, node) {
502 if (dev->features & LITEST_IGNORED)
503 continue;
504
505 if (filter_device &&
506 strstr(dev->shortname, filter_device) == NULL &&
507 fnmatch(filter_device, dev->shortname, 0) != 0)
508 continue;
509 if ((dev->features & required) != required ||
510 (dev->features & excluded) != 0)
511 continue;
512
513 litest_add_tcase_for_device(suite,
514 funcname,
515 func,
516 dev,
517 range);
518 added = true;
519 }
520 } else {
521 struct litest_test_device *dev;
522
523 list_for_each(dev, &devices, node) {
524 if (dev->features & LITEST_IGNORED)
525 continue;
526
527 if (filter_device &&
528 strstr(dev->shortname, filter_device) == NULL &&
529 fnmatch(filter_device, dev->shortname, 0) != 0)
530 continue;
531
532 litest_add_tcase_for_device(suite,
533 funcname,
534 func,
535 dev,
536 range);
537 added = true;
538 }
539 }
540
541 if (!added &&
542 filter_test == NULL &&
543 filter_device == NULL &&
544 filter_group == NULL) {
545 fprintf(stderr, "Test '%s' does not match any devices. Aborting.\n", funcname);
546 abort();
547 }
548 }
549
550 void
_litest_add_no_device(const char * name,const char * funcname,const void * func)551 _litest_add_no_device(const char *name, const char *funcname, const void *func)
552 {
553 _litest_add(name, funcname, func, LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE);
554 }
555
556 void
_litest_add_ranged_no_device(const char * name,const char * funcname,const void * func,const struct range * range)557 _litest_add_ranged_no_device(const char *name,
558 const char *funcname,
559 const void *func,
560 const struct range *range)
561 {
562 _litest_add_ranged(name,
563 funcname,
564 func,
565 LITEST_DISABLE_DEVICE,
566 LITEST_DISABLE_DEVICE,
567 range);
568 }
569
570 void
_litest_add_deviceless(const char * name,const char * funcname,const void * func)571 _litest_add_deviceless(const char *name,
572 const char *funcname,
573 const void *func)
574 {
575 _litest_add_ranged(name,
576 funcname,
577 func,
578 LITEST_DEVICELESS,
579 LITEST_DEVICELESS,
580 NULL);
581 }
582
583 void
_litest_add(const char * name,const char * funcname,const void * func,int64_t required,int64_t excluded)584 _litest_add(const char *name,
585 const char *funcname,
586 const void *func,
587 int64_t required,
588 int64_t excluded)
589 {
590 _litest_add_ranged(name,
591 funcname,
592 func,
593 required,
594 excluded,
595 NULL);
596 }
597
598 void
_litest_add_ranged(const char * name,const char * funcname,const void * func,int64_t required,int64_t excluded,const struct range * range)599 _litest_add_ranged(const char *name,
600 const char *funcname,
601 const void *func,
602 int64_t required,
603 int64_t excluded,
604 const struct range *range)
605 {
606 litest_add_tcase(name, funcname, func, required, excluded, range);
607 }
608
609 void
_litest_add_for_device(const char * name,const char * funcname,const void * func,enum litest_device_type type)610 _litest_add_for_device(const char *name,
611 const char *funcname,
612 const void *func,
613 enum litest_device_type type)
614 {
615 _litest_add_ranged_for_device(name, funcname, func, type, NULL);
616 }
617
618 void
_litest_add_ranged_for_device(const char * name,const char * funcname,const void * func,enum litest_device_type type,const struct range * range)619 _litest_add_ranged_for_device(const char *name,
620 const char *funcname,
621 const void *func,
622 enum litest_device_type type,
623 const struct range *range)
624 {
625 struct suite *s;
626 struct litest_test_device *dev;
627 bool device_filtered = false;
628
629 litest_assert(type < LITEST_NO_DEVICE);
630
631 if (filter_test &&
632 strstr(funcname, filter_test) == NULL &&
633 fnmatch(filter_test, funcname, 0) != 0)
634 return;
635
636 if (filter_group &&
637 strstr(name, filter_group) == NULL &&
638 fnmatch(filter_group, name, 0) != 0)
639 return;
640
641 s = get_suite(name);
642 list_for_each(dev, &devices, node) {
643 if (filter_device &&
644 strstr(dev->shortname, filter_device) == NULL &&
645 fnmatch(filter_device, dev->shortname, 0) != 0) {
646 device_filtered = true;
647 continue;
648 }
649
650 if (dev->type == type) {
651 litest_add_tcase_for_device(s,
652 funcname,
653 func,
654 dev,
655 range);
656 return;
657 }
658 }
659
660 /* only abort if no filter was set, that's a bug */
661 if (!device_filtered)
662 litest_abort_msg("Invalid test device type\n");
663 }
664
665 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
666 static void
litest_log_handler(struct libinput * libinput,enum libinput_log_priority pri,const char * format,va_list args)667 litest_log_handler(struct libinput *libinput,
668 enum libinput_log_priority pri,
669 const char *format,
670 va_list args)
671 {
672 static int is_tty = -1;
673 const char *priority = NULL;
674 const char *color;
675
676 if (is_tty == -1)
677 is_tty = isatty(STDERR_FILENO);
678
679 switch(pri) {
680 case LIBINPUT_LOG_PRIORITY_INFO:
681 priority = "info ";
682 color = ANSI_HIGHLIGHT;
683 break;
684 case LIBINPUT_LOG_PRIORITY_ERROR:
685 priority = "error";
686 color = ANSI_BRIGHT_RED;
687 break;
688 case LIBINPUT_LOG_PRIORITY_DEBUG:
689 priority = "debug";
690 color = ANSI_NORMAL;
691 break;
692 default:
693 abort();
694 }
695
696 if (!is_tty)
697 color = "";
698 else if (strstr(format, "tap:"))
699 color = ANSI_BLUE;
700 else if (strstr(format, "thumb state:"))
701 color = ANSI_YELLOW;
702 else if (strstr(format, "button state:"))
703 color = ANSI_MAGENTA;
704 else if (strstr(format, "touch-size:") ||
705 strstr(format, "pressure:"))
706 color = ANSI_GREEN;
707 else if (strstr(format, "palm:") ||
708 strstr(format, "thumb:"))
709 color = ANSI_CYAN;
710 else if (strstr(format, "edge-scroll:"))
711 color = ANSI_BRIGHT_GREEN;
712
713 fprintf(stderr, "%slitest %s ", color, priority);
714 vfprintf(stderr, format, args);
715 if (is_tty)
716 fprintf(stderr, ANSI_NORMAL);
717
718 if (strstr(format, "client bug: ") ||
719 strstr(format, "libinput bug: ")) {
720 /* valgrind is too slow and some of our offsets are too
721 * short, don't abort if during a valgrind run we get a
722 * negative offset */
723 if ((RUNNING_ON_VALGRIND && in_debugger) ||
724 !strstr(format, "scheduled expiry is in the past")) {
725 /* noop */
726 } else if (!strstr(format, "event processing lagging behind")) {
727 /* noop */
728 } else {
729 litest_abort_msg("libinput bug triggered, aborting.\n");
730 }
731 }
732
733 if (strstr(format, "Touch jump detected and discarded")) {
734 litest_abort_msg("libinput touch jump triggered, aborting.\n");
735 }
736 }
737
738 static void
litest_init_device_udev_rules(struct litest_test_device * dev,FILE * f)739 litest_init_device_udev_rules(struct litest_test_device *dev, FILE *f)
740 {
741 const struct key_value_str *kv;
742 static int count;
743 bool need_keyboard_builtin = false;
744
745 if (dev->udev_properties[0].key == NULL)
746 return;
747
748 count++;
749
750 fprintf(f, "# %s\n", dev->shortname);
751 fprintf(f, "ACTION==\"remove\", GOTO=\"rule%d_end\"\n", count);
752 fprintf(f, "KERNEL!=\"event*\", GOTO=\"rule%d_end\"\n", count);
753
754 fprintf(f, "ATTRS{name}==\"litest %s*\"", dev->name);
755
756 kv = dev->udev_properties;
757 while (kv->key) {
758 fprintf(f, ", \\\n\tENV{%s}=\"%s\"", kv->key, kv->value);
759 if (strneq(kv->key, "EVDEV_ABS_", 10))
760 need_keyboard_builtin = true;
761 kv++;
762 }
763 fprintf(f, "\n");
764
765 /* Special case: the udev keyboard builtin is only run for hwdb
766 * matches but we don't set any up in litest. So instead scan the
767 * device's udev properties for any EVDEV_ABS properties and where
768 * they exist, force a (re-)run of the keyboard builtin to set up
769 * the evdev device correctly.
770 * This needs to be done as separate rule apparently, otherwise the
771 * ENV variables aren't set yet by the time the builtin runs.
772 */
773 if (need_keyboard_builtin) {
774 fprintf(f, ""
775 "ATTRS{name}==\"litest %s*\","
776 " IMPORT{builtin}=\"keyboard\"\n",
777 dev->name);
778 }
779
780 fprintf(f, "LABEL=\"rule%d_end\"\n\n", count);;
781 }
782
783 static void
litest_init_all_device_udev_rules(struct list * created_files)784 litest_init_all_device_udev_rules(struct list *created_files)
785 {
786 struct created_file *file = zalloc(sizeof(*file));
787 struct litest_test_device *dev;
788 char *path = NULL;
789 FILE *f;
790 int rc;
791 int fd;
792
793 rc = xasprintf(&path,
794 "%s/99-litest-XXXXXX.rules",
795 UDEV_RULES_D);
796 litest_assert_int_gt(rc, 0);
797
798 fd = mkstemps(path, 6);
799 litest_assert_int_ne(fd, -1);
800 f = fdopen(fd, "w");
801 litest_assert_notnull(f);
802
803 list_for_each(dev, &devices, node)
804 litest_init_device_udev_rules(dev, f);
805
806 fclose(f);
807
808 file->path = path;
809 list_insert(created_files, &file->link);
810 }
811
812 static int
open_restricted(const char * path,int flags,void * userdata)813 open_restricted(const char *path, int flags, void *userdata)
814 {
815 const char prefix[] = "/dev/input/event";
816 struct litest_context *ctx = userdata;
817 struct path *p;
818 int fd;
819
820 litest_assert_ptr_notnull(ctx);
821
822 fd = open(path, flags);
823 if (fd < 0)
824 return -errno;
825
826 if (strneq(path, prefix, strlen(prefix))) {
827 p = zalloc(sizeof *p);
828 p->path = safe_strdup(path);
829 p->fd = fd;
830 /* We specifically insert here so that the most-recently
831 * opened path is the first one in the list. This helps when
832 * we have multiple test devices with the same device path,
833 * the fd of the most recent device is the first one to get
834 * grabbed
835 */
836 list_insert(&ctx->paths, &p->link);
837 }
838
839 return fd;
840 }
841
842 static void
close_restricted(int fd,void * userdata)843 close_restricted(int fd, void *userdata)
844 {
845 struct litest_context *ctx = userdata;
846 struct path *p, *tmp;
847
848 list_for_each_safe(p, tmp, &ctx->paths, link) {
849 if (p->fd != fd)
850 continue;
851 list_remove(&p->link);
852 free(p->path);
853 free(p);
854 }
855
856 close(fd);
857 }
858
859 struct libinput_interface interface = {
860 .open_restricted = open_restricted,
861 .close_restricted = close_restricted,
862 };
863
864 static void
litest_signal(int sig)865 litest_signal(int sig)
866 {
867 struct created_file *f, *tmp;
868
869 list_for_each_safe(f, tmp, &created_files_list, link) {
870 list_remove(&f->link);
871 unlink(f->path);
872 rmdir(f->path);
873 /* in the sighandler, we can't free */
874 }
875
876 if (fork() == 0) {
877 /* child, we can run system() */
878 litest_reload_udev_rules();
879 exit(0);
880 }
881
882 exit(1);
883 }
884
885 static inline void
litest_setup_sighandler(int sig)886 litest_setup_sighandler(int sig)
887 {
888 struct sigaction act, oact;
889 int rc;
890
891 sigemptyset(&act.sa_mask);
892 sigaddset(&act.sa_mask, sig);
893 act.sa_flags = 0;
894 act.sa_handler = litest_signal;
895 rc = sigaction(sig, &act, &oact);
896 litest_assert_int_ne(rc, -1);
897 }
898
899 static void
litest_free_test_list(struct list * tests)900 litest_free_test_list(struct list *tests)
901 {
902 struct suite *s, *snext;
903
904 list_for_each_safe(s, snext, tests, node) {
905 struct test *t, *tnext;
906
907 list_for_each_safe(t, tnext, &s->tests, node) {
908 free(t->name);
909 free(t->devname);
910 list_remove(&t->node);
911 free(t);
912 }
913
914 list_remove(&s->node);
915 free(s->name);
916 free(s);
917 }
918 }
919
920 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
921 static inline void
quirk_log_handler(struct libinput * unused,enum libinput_log_priority priority,const char * format,va_list args)922 quirk_log_handler(struct libinput *unused,
923 enum libinput_log_priority priority,
924 const char *format,
925 va_list args)
926 {
927 if (priority < LIBINPUT_LOG_PRIORITY_ERROR)
928 return;
929
930 vfprintf(stderr, format, args);
931 }
932
933 static void
litest_export_xml(SRunner * sr,const char * xml_prefix)934 litest_export_xml(SRunner *sr, const char *xml_prefix)
935 {
936 TestResult **results;
937 int nresults, nfailed;
938 char *filename;
939 int fd;
940
941 /* This is the minimum-effort implementation here because its only
942 * real purpose is to make test logs look pretty in the gitlab CI.
943 *
944 * Which means:
945 * - there's no filename validation, if you supply a filename that
946 * mkstemps doesn't like, things go boom.
947 * - every fork writes out a separate junit.xml file. gitlab is better
948 * at collecting lots of files than I am at writing code to collect
949 * this across forks to write out only one file.
950 * - most of the content is pretty useless because libcheck only gives
951 * us minimal information. the libcheck XML file has more info like
952 * the duration of each test but it's more complicated to extract
953 * and we don't need it for now.
954 */
955 filename = safe_strdup(xml_prefix);
956 fd = mkstemps(filename, 4);
957
958 results = srunner_results(sr);
959 nresults = srunner_ntests_run(sr);
960 nfailed = srunner_ntests_failed(sr);
961
962 dprintf(fd, "<?xml version=\"1.0\"?>\n");
963 dprintf(fd, "<testsuites id=\"%s\" tests=\"%d\" failures=\"%d\">\n",
964 filename,
965 nresults,
966 nfailed);
967 dprintf(fd, " <testsuite>\n");
968 for (int i = 0; i < nresults; i++) {
969 TestResult *r = results[i];
970
971 dprintf(fd, " <testcase id=\"%s\" name=\"%s\" %s>\n",
972 tr_tcname(r),
973 tr_tcname(r),
974 tr_rtype(r) == CK_PASS ? "/" : "");
975 if (tr_rtype(r) != CK_PASS) {
976 dprintf(fd, " <failure message=\"%s:%d\">\n",
977 tr_lfile(r),
978 tr_lno(r));
979 dprintf(fd, " %s:%d\n", tr_lfile(r), tr_lno(r));
980 dprintf(fd, " %s\n", tr_tcname(r));
981 dprintf(fd, "\n");
982 dprintf(fd, " %s\n", tr_msg(r));
983 dprintf(fd, " </failure>\n");
984 dprintf(fd, " </testcase>\n");
985 }
986 }
987 dprintf(fd, " </testsuite>\n");
988 dprintf(fd, "</testsuites>\n");
989
990 free(results);
991 close(fd);
992 free(filename);
993 }
994
995 static int
litest_run_suite(struct list * tests,int which,int max,int error_fd)996 litest_run_suite(struct list *tests, int which, int max, int error_fd)
997 {
998 int failed = 0;
999 SRunner *sr = NULL;
1000 struct suite *s;
1001 struct test *t;
1002 int count = -1;
1003 struct name {
1004 struct list node;
1005 char *name;
1006 };
1007 struct name *n, *tmp;
1008 struct list testnames;
1009 const char *data_path;
1010
1011 data_path = getenv("LIBINPUT_QUIRKS_DIR");
1012 if (!data_path)
1013 data_path = LIBINPUT_QUIRKS_DIR;
1014
1015 quirks_context = quirks_init_subsystem(data_path,
1016 NULL,
1017 quirk_log_handler,
1018 NULL,
1019 QLOG_LIBINPUT_LOGGING);
1020
1021 /* Check just takes the suite/test name pointers but doesn't strdup
1022 * them - we have to keep them around */
1023 list_init(&testnames);
1024
1025 /* For each test, create one test suite with one test case, then
1026 add it to the test runner. The only benefit suites give us in
1027 check is that we can filter them, but our test runner has a
1028 --filter-group anyway. */
1029 list_for_each(s, tests, node) {
1030 list_for_each(t, &s->tests, node) {
1031 Suite *suite;
1032 TCase *tc;
1033 char *sname, *tname;
1034
1035 /* We run deviceless tests as part of the normal
1036 * test suite runner, just in case. Filtering
1037 * all the other ones out just for the case where
1038 * we can't run the full runner.
1039 */
1040 if (run_deviceless && !t->deviceless)
1041 continue;
1042
1043 count = (count + 1) % max;
1044 if (max != 1 && (count % max) != which)
1045 continue;
1046
1047 xasprintf(&sname,
1048 "%s:%s:%s",
1049 s->name,
1050 t->name,
1051 t->devname);
1052 litest_assert_ptr_notnull(sname);
1053 n = zalloc(sizeof(*n));
1054 n->name = sname;
1055 list_insert(&testnames, &n->node);
1056
1057 xasprintf(&tname,
1058 "%s:%s",
1059 t->name,
1060 t->devname);
1061 litest_assert_ptr_notnull(tname);
1062 n = zalloc(sizeof(*n));
1063 n->name = tname;
1064 list_insert(&testnames, &n->node);
1065
1066 tc = tcase_create(tname);
1067 tcase_add_checked_fixture(tc,
1068 t->setup,
1069 t->teardown);
1070 if (t->range.upper != t->range.lower)
1071 tcase_add_loop_test(tc,
1072 t->func,
1073 t->range.lower,
1074 t->range.upper);
1075 else
1076 tcase_add_test(tc, t->func);
1077
1078 suite = suite_create(sname);
1079 suite_add_tcase(suite, tc);
1080
1081 if (!sr)
1082 sr = srunner_create(suite);
1083 else
1084 srunner_add_suite(sr, suite);
1085 }
1086 }
1087
1088 if (!sr)
1089 goto out;
1090
1091 srunner_run_all(sr, CK_ENV);
1092 if (xml_prefix)
1093 litest_export_xml(sr, xml_prefix);
1094
1095
1096 failed = srunner_ntests_failed(sr);
1097 if (failed) {
1098 TestResult **trs;
1099
1100 trs = srunner_failures(sr);
1101 for (int i = 0; i < failed; i++) {
1102 char tname[256];
1103 char *c = tname;
1104
1105 /* tr_tcname is in the form "suite:testcase", let's
1106 * convert this to "suite(testcase)" to make
1107 * double-click selection in the terminal a bit
1108 * easier. */
1109 snprintf(tname, sizeof(tname), "%s)", tr_tcname(trs[i]));
1110 if ((c = index(c, ':')))
1111 *c = '(';
1112
1113 dprintf(error_fd,
1114 ":: Failure: %s:%d: %s\n",
1115 tr_lfile(trs[i]),
1116 tr_lno(trs[i]),
1117 tname);
1118 }
1119 free(trs);
1120 }
1121 srunner_free(sr);
1122 out:
1123 list_for_each_safe(n, tmp, &testnames, node) {
1124 free(n->name);
1125 free(n);
1126 }
1127
1128 quirks_context_unref(quirks_context);
1129
1130 return failed;
1131 }
1132
1133 static int
litest_fork_subtests(struct list * tests,int max_forks)1134 litest_fork_subtests(struct list *tests, int max_forks)
1135 {
1136 int failed = 0;
1137 int status;
1138 pid_t pid;
1139 int f;
1140 int pipes[max_forks];
1141
1142 for (f = 0; f < max_forks; f++) {
1143 int rc;
1144 int pipefd[2];
1145
1146 rc = pipe2(pipefd, O_NONBLOCK);
1147 assert(rc != -1);
1148
1149 pid = fork();
1150 if (pid == 0) {
1151 close(pipefd[0]);
1152 failed = litest_run_suite(tests,
1153 f,
1154 max_forks,
1155 pipefd[1]);
1156
1157 litest_free_test_list(&all_tests);
1158 exit(failed);
1159 /* child always exits here */
1160 } else {
1161 pipes[f] = pipefd[0];
1162 close(pipefd[1]);
1163 }
1164 }
1165
1166 /* parent process only */
1167 while (wait(&status) != -1 && errno != ECHILD) {
1168 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
1169 failed = 1;
1170 }
1171
1172 for (f = 0; f < max_forks; f++) {
1173 char buf[1024] = {0};
1174 int rc;
1175
1176 while ((rc = read(pipes[f], buf, sizeof(buf) - 1)) > 0) {
1177 buf[rc] = '\0';
1178 fprintf(stderr, "%s", buf);
1179 }
1180
1181 close(pipes[f]);
1182 }
1183
1184 return failed;
1185 }
1186
1187 static inline int
inhibit(void)1188 inhibit(void)
1189 {
1190 int lock_fd = -1;
1191 #if HAVE_LIBSYSTEMD
1192 sd_bus_error error = SD_BUS_ERROR_NULL;
1193 sd_bus_message *m = NULL;
1194 sd_bus *bus = NULL;
1195 int rc;
1196
1197 if (run_deviceless)
1198 return -1;
1199
1200 rc = sd_bus_open_system(&bus);
1201 if (rc != 0) {
1202 fprintf(stderr, "Warning: inhibit failed: %s\n", strerror(-rc));
1203 goto out;
1204 }
1205
1206 rc = sd_bus_call_method(bus,
1207 "org.freedesktop.login1",
1208 "/org/freedesktop/login1",
1209 "org.freedesktop.login1.Manager",
1210 "Inhibit",
1211 &error,
1212 &m,
1213 "ssss",
1214 "sleep:shutdown:handle-lid-switch:handle-power-key:handle-suspend-key:handle-hibernate-key",
1215 "libinput test-suite runner",
1216 "testing in progress",
1217 "block");
1218 if (rc < 0) {
1219 fprintf(stderr, "Warning: inhibit failed: %s\n", error.message);
1220 goto out;
1221 }
1222
1223 rc = sd_bus_message_read(m, "h", &lock_fd);
1224 if (rc < 0) {
1225 fprintf(stderr, "Warning: inhibit failed: %s\n", strerror(-rc));
1226 goto out;
1227 }
1228
1229 lock_fd = dup(lock_fd);
1230 out:
1231 sd_bus_error_free(&error);
1232 sd_bus_message_unref(m);
1233 sd_bus_close(bus);
1234 sd_bus_unref(bus);
1235 #endif
1236 return lock_fd;
1237 }
1238
1239 static inline int
litest_run(int argc,char ** argv)1240 litest_run(int argc, char **argv)
1241 {
1242 int failed = 0;
1243 int inhibit_lock_fd;
1244
1245 list_init(&created_files_list);
1246
1247 if (list_empty(&all_tests)) {
1248 fprintf(stderr,
1249 "Error: filters are too strict, no tests to run.\n");
1250 return 1;
1251 }
1252
1253 if (getenv("LITEST_VERBOSE"))
1254 verbose = true;
1255
1256 if (run_deviceless) {
1257 litest_setup_quirks(&created_files_list,
1258 QUIRKS_SETUP_USE_SRCDIR);
1259 } else {
1260 enum quirks_setup_mode mode;
1261 litest_init_udev_rules(&created_files_list);
1262
1263
1264 mode = use_system_rules_quirks ?
1265 QUIRKS_SETUP_ONLY_DEVICE :
1266 QUIRKS_SETUP_FULL;
1267 litest_setup_quirks(&created_files_list, mode);
1268 }
1269
1270 litest_setup_sighandler(SIGINT);
1271
1272 inhibit_lock_fd = inhibit();
1273
1274 if (jobs == 1)
1275 failed = litest_run_suite(&all_tests, 1, 1, STDERR_FILENO);
1276 else
1277 failed = litest_fork_subtests(&all_tests, jobs);
1278
1279 close(inhibit_lock_fd);
1280
1281 litest_free_test_list(&all_tests);
1282
1283 litest_remove_udev_rules(&created_files_list);
1284
1285 return failed;
1286 }
1287
1288 static struct input_absinfo *
merge_absinfo(const struct input_absinfo * orig,const struct input_absinfo * override)1289 merge_absinfo(const struct input_absinfo *orig,
1290 const struct input_absinfo *override)
1291 {
1292 struct input_absinfo *abs;
1293 unsigned int nelem, i;
1294 size_t sz = ABS_MAX + 1;
1295
1296 if (!orig)
1297 return NULL;
1298
1299 abs = zalloc(sz * sizeof(*abs));
1300 litest_assert_ptr_notnull(abs);
1301
1302 nelem = 0;
1303 while (orig[nelem].value != -1) {
1304 abs[nelem] = orig[nelem];
1305 nelem++;
1306 litest_assert_int_lt(nelem, sz);
1307 }
1308
1309 /* just append, if the same axis is present twice, libevdev will
1310 only use the last value anyway */
1311 i = 0;
1312 while (override && override[i].value != -1) {
1313 abs[nelem++] = override[i++];
1314 litest_assert_int_lt(nelem, sz);
1315 }
1316
1317 litest_assert_int_lt(nelem, sz);
1318 abs[nelem].value = -1;
1319
1320 return abs;
1321 }
1322
1323 static int*
merge_events(const int * orig,const int * override)1324 merge_events(const int *orig, const int *override)
1325 {
1326 int *events;
1327 unsigned int nelem, i;
1328 size_t sz = KEY_MAX * 3;
1329
1330 if (!orig)
1331 return NULL;
1332
1333 events = zalloc(sz * sizeof(int));
1334 litest_assert_ptr_notnull(events);
1335
1336 nelem = 0;
1337 while (orig[nelem] != -1) {
1338 events[nelem] = orig[nelem];
1339 nelem++;
1340 litest_assert_int_lt(nelem, sz);
1341 }
1342
1343 /* just append, if the same axis is present twice, libevdev will
1344 * ignore the double definition anyway */
1345 i = 0;
1346 while (override && override[i] != -1) {
1347 events[nelem++] = override[i++];
1348 litest_assert_int_le(nelem, sz);
1349 }
1350
1351 litest_assert_int_lt(nelem, sz);
1352 events[nelem] = -1;
1353
1354 return events;
1355 }
1356
1357 static inline struct created_file *
litest_copy_file(const char * dest,const char * src,const char * header,bool is_file)1358 litest_copy_file(const char *dest, const char *src, const char *header, bool is_file)
1359 {
1360 int in, out, length;
1361 struct created_file *file;
1362
1363 file = zalloc(sizeof(*file));
1364 file->path = safe_strdup(dest);
1365
1366 if (strstr(dest, "XXXXXX")) {
1367 int suffixlen;
1368
1369 suffixlen = file->path +
1370 strlen(file->path) -
1371 rindex(file->path, '.');
1372 out = mkstemps(file->path, suffixlen);
1373 } else {
1374 out = open(file->path, O_CREAT|O_WRONLY, 0644);
1375 }
1376 if (out == -1)
1377 litest_abort_msg("Failed to write to file %s (%s)\n",
1378 file->path,
1379 strerror(errno));
1380 litest_assert_int_ne(chmod(file->path, 0644), -1);
1381
1382 if (header) {
1383 length = strlen(header);
1384 litest_assert_int_eq(write(out, header, length), length);
1385 }
1386
1387 if (is_file) {
1388 in = open(src, O_RDONLY);
1389 if (in == -1)
1390 litest_abort_msg("Failed to open file %s (%s)\n",
1391 src,
1392 strerror(errno));
1393 /* lazy, just check for error and empty file copy */
1394 litest_assert_int_gt(litest_send_file(out, in), 0);
1395 close(in);
1396 } else {
1397 size_t written = write(out, src, strlen(src));
1398 litest_assert_int_eq(written, strlen(src));
1399
1400 }
1401 close(out);
1402
1403 return file;
1404 }
1405
1406 static inline void
litest_install_model_quirks(struct list * created_files_list)1407 litest_install_model_quirks(struct list *created_files_list)
1408 {
1409 const char *warning =
1410 "#################################################################\n"
1411 "# WARNING: REMOVE THIS FILE\n"
1412 "# This is a run-time file for the libinput test suite and\n"
1413 "# should be removed on exit. If the test-suite is not currently \n"
1414 "# running, remove this file\n"
1415 "#################################################################\n\n";
1416 struct created_file *file;
1417 const char *test_device_udev_rule = "KERNELS==\"*input*\", "
1418 "ATTRS{name}==\"litest *\", "
1419 "ENV{LIBINPUT_TEST_DEVICE}=\"1\"";
1420
1421 file = litest_copy_file(UDEV_TEST_DEVICE_RULE_FILE,
1422 test_device_udev_rule,
1423 warning,
1424 false);
1425 list_insert(created_files_list, &file->link);
1426
1427 /* Ony install the litest device rule when we're running as system
1428 * test suite, we expect the others to be in place already */
1429 if (use_system_rules_quirks)
1430 return;
1431
1432 file = litest_copy_file(UDEV_DEVICE_GROUPS_FILE,
1433 LIBINPUT_DEVICE_GROUPS_RULES_FILE,
1434 warning,
1435 true);
1436 list_insert(created_files_list, &file->link);
1437
1438 file = litest_copy_file(UDEV_FUZZ_OVERRIDE_RULE_FILE,
1439 LIBINPUT_FUZZ_OVERRIDE_UDEV_RULES_FILE,
1440 warning,
1441 true);
1442 list_insert(created_files_list, &file->link);
1443 }
1444
1445 static char *
litest_init_device_quirk_file(const char * data_dir,struct litest_test_device * dev)1446 litest_init_device_quirk_file(const char *data_dir,
1447 struct litest_test_device *dev)
1448 {
1449 int fd;
1450 FILE *f;
1451 char path[PATH_MAX];
1452 static int count;
1453
1454 if (!dev->quirk_file)
1455 return NULL;
1456
1457 snprintf(path, sizeof(path),
1458 "%s/99-%03d-%s.quirks",
1459 data_dir,
1460 ++count,
1461 dev->shortname);
1462 fd = open(path, O_CREAT|O_WRONLY, 0644);
1463 litest_assert_int_ne(fd, -1);
1464 f = fdopen(fd, "w");
1465 litest_assert_notnull(f);
1466 litest_assert_int_ge(fputs(dev->quirk_file, f), 0);
1467 fclose(f);
1468
1469 return safe_strdup(path);
1470 }
1471
is_quirks_file(const struct dirent * dir)1472 static int is_quirks_file(const struct dirent *dir) {
1473 return strendswith(dir->d_name, ".quirks");
1474 }
1475
1476 /**
1477 * Install the quirks from the quirks/ source directory.
1478 */
1479 static void
litest_install_source_quirks(struct list * created_files_list,const char * dirname)1480 litest_install_source_quirks(struct list *created_files_list,
1481 const char *dirname)
1482 {
1483 struct dirent **namelist;
1484 int ndev;
1485
1486 ndev = scandir(LIBINPUT_QUIRKS_SRCDIR,
1487 &namelist,
1488 is_quirks_file,
1489 versionsort);
1490 litest_assert_int_ge(ndev, 0);
1491
1492 for (int idx = 0; idx < ndev; idx++) {
1493 struct created_file *file;
1494 char *filename;
1495 char dest[PATH_MAX];
1496 char src[PATH_MAX];
1497
1498 filename = namelist[idx]->d_name;
1499 snprintf(src, sizeof(src), "%s/%s",
1500 LIBINPUT_QUIRKS_SRCDIR, filename);
1501 snprintf(dest, sizeof(dest), "%s/%s", dirname, filename);
1502 file = litest_copy_file(dest, src, NULL, true);
1503 list_append(created_files_list, &file->link);
1504 free(namelist[idx]);
1505 }
1506 free(namelist);
1507 }
1508
1509 /**
1510 * Install the quirks from the various litest test devices
1511 */
1512 static void
litest_install_device_quirks(struct list * created_files_list,const char * dirname)1513 litest_install_device_quirks(struct list *created_files_list,
1514 const char *dirname)
1515 {
1516 struct litest_test_device *dev;
1517
1518 list_for_each(dev, &devices, node) {
1519 char *path;
1520
1521 path = litest_init_device_quirk_file(dirname, dev);
1522 if (path) {
1523 struct created_file *file = zalloc(sizeof(*file));
1524 file->path = path;
1525 list_insert(created_files_list, &file->link);
1526 }
1527 }
1528 }
1529
1530 static void
litest_setup_quirks(struct list * created_files_list,enum quirks_setup_mode mode)1531 litest_setup_quirks(struct list *created_files_list,
1532 enum quirks_setup_mode mode)
1533 {
1534 struct created_file *file = NULL;
1535 const char *dirname;
1536 char tmpdir[] = "/run/litest-XXXXXX";
1537
1538 switch (mode) {
1539 case QUIRKS_SETUP_USE_SRCDIR:
1540 dirname = LIBINPUT_QUIRKS_SRCDIR;
1541 break;
1542 case QUIRKS_SETUP_ONLY_DEVICE:
1543 dirname = LIBINPUT_QUIRKS_DIR;
1544 litest_install_device_quirks(created_files_list, dirname);
1545 break;
1546 case QUIRKS_SETUP_FULL:
1547 litest_assert_notnull(mkdtemp(tmpdir));
1548 litest_assert_int_ne(chmod(tmpdir, 0755), -1);
1549 file = zalloc(sizeof *file);
1550 file->path = safe_strdup(tmpdir);
1551 dirname = tmpdir;
1552
1553 litest_install_source_quirks(created_files_list, dirname);
1554 litest_install_device_quirks(created_files_list, dirname);
1555 list_append(created_files_list, &file->link);
1556 break;
1557 }
1558
1559 setenv("LIBINPUT_QUIRKS_DIR", dirname, 1);
1560 }
1561
1562 static inline void
mkdir_p(const char * dir)1563 mkdir_p(const char *dir)
1564 {
1565 char *path, *parent;
1566 int rc;
1567
1568 if (streq(dir, "/"))
1569 return;
1570
1571 path = strdup(dir);
1572 parent = dirname(path);
1573
1574 mkdir_p(parent);
1575 rc = mkdir(dir, 0755);
1576
1577 if (rc == -1 && errno != EEXIST) {
1578 litest_abort_msg("Failed to create directory %s (%s)\n",
1579 dir,
1580 strerror(errno));
1581 }
1582
1583 free(path);
1584 }
1585
1586 static inline void
litest_init_udev_rules(struct list * created_files)1587 litest_init_udev_rules(struct list *created_files)
1588 {
1589 mkdir_p(UDEV_RULES_D);
1590
1591 litest_install_model_quirks(created_files);
1592 litest_init_all_device_udev_rules(created_files);
1593 litest_reload_udev_rules();
1594 }
1595
1596 static inline void
litest_remove_udev_rules(struct list * created_files_list)1597 litest_remove_udev_rules(struct list *created_files_list)
1598 {
1599 struct created_file *f, *tmp;
1600 bool reload_udev;
1601
1602 reload_udev = !list_empty(created_files_list);
1603
1604 list_for_each_safe(f, tmp, created_files_list, link) {
1605 list_remove(&f->link);
1606 unlink(f->path);
1607 rmdir(f->path);
1608 free(f->path);
1609 free(f);
1610 }
1611
1612 if (reload_udev)
1613 litest_reload_udev_rules();
1614 }
1615
1616 /**
1617 * Creates a uinput device but does not add it to a libinput context
1618 */
1619 struct litest_device *
litest_create(enum litest_device_type which,const char * name_override,struct input_id * id_override,const struct input_absinfo * abs_override,const int * events_override)1620 litest_create(enum litest_device_type which,
1621 const char *name_override,
1622 struct input_id *id_override,
1623 const struct input_absinfo *abs_override,
1624 const int *events_override)
1625 {
1626 struct litest_device *d = NULL;
1627 struct litest_test_device *dev;
1628 const char *name;
1629 const struct input_id *id;
1630 struct input_absinfo *abs;
1631 int *events, *e;
1632 const char *path;
1633 int fd, rc;
1634 bool found = false;
1635 bool create_device = true;
1636
1637 list_for_each(dev, &devices, node) {
1638 if (dev->type == which) {
1639 found = true;
1640 break;
1641 }
1642 }
1643
1644 if (!found)
1645 ck_abort_msg("Invalid device type %d\n", which);
1646
1647 d = zalloc(sizeof(*d));
1648 d->which = which;
1649
1650 /* device has custom create method */
1651 if (dev->create) {
1652 create_device = dev->create(d);
1653 if (abs_override || events_override) {
1654 litest_abort_msg("Custom create cannot be overridden");
1655 }
1656 }
1657
1658 abs = merge_absinfo(dev->absinfo, abs_override);
1659 events = merge_events(dev->events, events_override);
1660 name = name_override ? name_override : dev->name;
1661 id = id_override ? id_override : dev->id;
1662
1663 if (create_device) {
1664 d->uinput = litest_create_uinput_device_from_description(name,
1665 id,
1666 abs,
1667 events);
1668 d->interface = dev->interface;
1669
1670 for (e = events; *e != -1; e += 2) {
1671 unsigned int type = *e,
1672 code = *(e + 1);
1673
1674 if (type == INPUT_PROP_MAX &&
1675 code == INPUT_PROP_SEMI_MT) {
1676 d->semi_mt.is_semi_mt = true;
1677 break;
1678 }
1679 }
1680 }
1681
1682 free(abs);
1683 free(events);
1684
1685 path = libevdev_uinput_get_devnode(d->uinput);
1686 litest_assert_ptr_notnull(path);
1687 fd = open(path, O_RDWR|O_NONBLOCK);
1688 litest_assert_int_ne(fd, -1);
1689
1690 rc = libevdev_new_from_fd(fd, &d->evdev);
1691 litest_assert_int_eq(rc, 0);
1692
1693 return d;
1694
1695 }
1696
1697 struct libinput *
litest_create_context(void)1698 litest_create_context(void)
1699 {
1700 struct libinput *libinput;
1701 struct litest_context *ctx;
1702
1703 ctx = zalloc(sizeof *ctx);
1704 list_init(&ctx->paths);
1705
1706 libinput = libinput_path_create_context(&interface, ctx);
1707 litest_assert_notnull(libinput);
1708
1709 libinput_log_set_handler(libinput, litest_log_handler);
1710 if (verbose)
1711 libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
1712
1713 return libinput;
1714 }
1715
1716 void
litest_destroy_context(struct libinput * li)1717 litest_destroy_context(struct libinput *li)
1718 {
1719 struct path *p, *tmp;
1720 struct litest_context *ctx;
1721
1722
1723 ctx = libinput_get_user_data(li);
1724 litest_assert_ptr_notnull(ctx);
1725 libinput_unref(li);
1726
1727 list_for_each_safe(p, tmp, &ctx->paths, link) {
1728 litest_abort_msg("Device paths should be removed by now");
1729 }
1730 free(ctx);
1731 }
1732
1733 void
litest_disable_log_handler(struct libinput * libinput)1734 litest_disable_log_handler(struct libinput *libinput)
1735 {
1736 libinput_log_set_handler(libinput, NULL);
1737 }
1738
1739 void
litest_restore_log_handler(struct libinput * libinput)1740 litest_restore_log_handler(struct libinput *libinput)
1741 {
1742 libinput_log_set_handler(libinput, litest_log_handler);
1743 if (verbose)
1744 libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
1745 }
1746
1747 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
1748 static void
litest_bug_log_handler(struct libinput * libinput,enum libinput_log_priority pri,const char * format,va_list args)1749 litest_bug_log_handler(struct libinput *libinput,
1750 enum libinput_log_priority pri,
1751 const char *format,
1752 va_list args)
1753 {
1754 if (strstr(format, "client bug: ") ||
1755 strstr(format, "libinput bug: "))
1756 return;
1757
1758 litest_abort_msg("Expected bug statement in log msg, aborting.\n");
1759 }
1760
1761 void
litest_set_log_handler_bug(struct libinput * libinput)1762 litest_set_log_handler_bug(struct libinput *libinput)
1763 {
1764 libinput_log_set_handler(libinput, litest_bug_log_handler);
1765 }
1766
1767 struct litest_device *
litest_add_device_with_overrides(struct libinput * libinput,enum litest_device_type which,const char * name_override,struct input_id * id_override,const struct input_absinfo * abs_override,const int * events_override)1768 litest_add_device_with_overrides(struct libinput *libinput,
1769 enum litest_device_type which,
1770 const char *name_override,
1771 struct input_id *id_override,
1772 const struct input_absinfo *abs_override,
1773 const int *events_override)
1774 {
1775 struct udev_device *ud;
1776 struct litest_device *d;
1777 const char *path;
1778
1779 d = litest_create(which,
1780 name_override,
1781 id_override,
1782 abs_override,
1783 events_override);
1784
1785 path = libevdev_uinput_get_devnode(d->uinput);
1786 litest_assert_ptr_notnull(path);
1787
1788 d->libinput = libinput;
1789 d->libinput_device = libinput_path_add_device(d->libinput, path);
1790 litest_assert_ptr_notnull(d->libinput_device);
1791 ud = libinput_device_get_udev_device(d->libinput_device);
1792 d->quirks = quirks_fetch_for_device(quirks_context, ud);
1793 udev_device_unref(ud);
1794
1795 libinput_device_ref(d->libinput_device);
1796
1797 if (d->interface) {
1798 unsigned int code;
1799
1800 code = ABS_X;
1801 if (!libevdev_has_event_code(d->evdev, EV_ABS, code))
1802 code = ABS_MT_POSITION_X;
1803 if (libevdev_has_event_code(d->evdev, EV_ABS, code)) {
1804 d->interface->min[ABS_X] = libevdev_get_abs_minimum(d->evdev, code);
1805 d->interface->max[ABS_X] = libevdev_get_abs_maximum(d->evdev, code);
1806 }
1807
1808 code = ABS_Y;
1809 if (!libevdev_has_event_code(d->evdev, EV_ABS, code))
1810 code = ABS_MT_POSITION_Y;
1811 if (libevdev_has_event_code(d->evdev, EV_ABS, code)) {
1812 d->interface->min[ABS_Y] = libevdev_get_abs_minimum(d->evdev, code);
1813 d->interface->max[ABS_Y] = libevdev_get_abs_maximum(d->evdev, code);
1814 }
1815 }
1816 return d;
1817 }
1818
1819 struct litest_device *
litest_add_device(struct libinput * libinput,enum litest_device_type which)1820 litest_add_device(struct libinput *libinput,
1821 enum litest_device_type which)
1822 {
1823 return litest_add_device_with_overrides(libinput,
1824 which,
1825 NULL,
1826 NULL,
1827 NULL,
1828 NULL);
1829 }
1830
1831 struct litest_device *
litest_create_device_with_overrides(enum litest_device_type which,const char * name_override,struct input_id * id_override,const struct input_absinfo * abs_override,const int * events_override)1832 litest_create_device_with_overrides(enum litest_device_type which,
1833 const char *name_override,
1834 struct input_id *id_override,
1835 const struct input_absinfo *abs_override,
1836 const int *events_override)
1837 {
1838 struct litest_device *dev =
1839 litest_add_device_with_overrides(litest_create_context(),
1840 which,
1841 name_override,
1842 id_override,
1843 abs_override,
1844 events_override);
1845 dev->owns_context = true;
1846 return dev;
1847 }
1848
1849 struct litest_device *
litest_create_device(enum litest_device_type which)1850 litest_create_device(enum litest_device_type which)
1851 {
1852 return litest_create_device_with_overrides(which, NULL, NULL, NULL, NULL);
1853 }
1854
1855 static struct udev_monitor *
udev_setup_monitor(void)1856 udev_setup_monitor(void)
1857 {
1858 struct udev *udev;
1859 struct udev_monitor *udev_monitor;
1860 int rc;
1861
1862 udev = udev_new();
1863 litest_assert_notnull(udev);
1864 udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
1865 litest_assert_notnull(udev_monitor);
1866 udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
1867 NULL);
1868
1869
1870 /* remove O_NONBLOCK */
1871 rc = fcntl(udev_monitor_get_fd(udev_monitor), F_SETFL, 0);
1872 litest_assert_int_ne(rc, -1);
1873 litest_assert_int_eq(udev_monitor_enable_receiving(udev_monitor),
1874 0);
1875 udev_unref(udev);
1876
1877 return udev_monitor;
1878 }
1879
1880 static struct udev_device *
udev_wait_for_device_event(struct udev_monitor * udev_monitor,const char * udev_event,const char * syspath)1881 udev_wait_for_device_event(struct udev_monitor *udev_monitor,
1882 const char *udev_event,
1883 const char *syspath)
1884 {
1885 struct udev_device *udev_device = NULL;
1886
1887 /* blocking, we don't want to continue until udev is ready */
1888 while (1) {
1889 const char *udev_syspath = NULL;
1890 const char *udev_action;
1891
1892 udev_device = udev_monitor_receive_device(udev_monitor);
1893 litest_assert_notnull(udev_device);
1894 udev_action = udev_device_get_action(udev_device);
1895 if (!streq(udev_action, udev_event)) {
1896 udev_device_unref(udev_device);
1897 continue;
1898 }
1899
1900 udev_syspath = udev_device_get_syspath(udev_device);
1901 if (udev_syspath && strstartswith(udev_syspath, syspath))
1902 break;
1903
1904 udev_device_unref(udev_device);
1905 }
1906
1907 return udev_device;
1908 }
1909
1910 void
litest_delete_device(struct litest_device * d)1911 litest_delete_device(struct litest_device *d)
1912 {
1913
1914 struct udev_monitor *udev_monitor;
1915 struct udev_device *udev_device;
1916 char path[PATH_MAX];
1917
1918 if (!d)
1919 return;
1920
1921 udev_monitor = udev_setup_monitor();
1922 snprintf(path, sizeof(path),
1923 "%s/event",
1924 libevdev_uinput_get_syspath(d->uinput));
1925
1926 litest_assert_int_eq(d->skip_ev_syn, 0);
1927
1928 quirks_unref(d->quirks);
1929
1930 if (d->libinput_device) {
1931 libinput_path_remove_device(d->libinput_device);
1932 libinput_device_unref(d->libinput_device);
1933 }
1934 if (d->owns_context) {
1935 libinput_dispatch(d->libinput);
1936 litest_destroy_context(d->libinput);
1937 }
1938 close(libevdev_get_fd(d->evdev));
1939 libevdev_free(d->evdev);
1940 libevdev_uinput_destroy(d->uinput);
1941 free(d->private);
1942 memset(d,0, sizeof(*d));
1943 free(d);
1944
1945 udev_device = udev_wait_for_device_event(udev_monitor,
1946 "remove",
1947 path);
1948 udev_device_unref(udev_device);
1949 udev_monitor_unref(udev_monitor);
1950 }
1951
1952 void
litest_event(struct litest_device * d,unsigned int type,unsigned int code,int value)1953 litest_event(struct litest_device *d, unsigned int type,
1954 unsigned int code, int value)
1955 {
1956 int ret;
1957
1958 if (!libevdev_has_event_code(d->evdev, type, code))
1959 return;
1960
1961 if (d->skip_ev_syn && type == EV_SYN && code == SYN_REPORT)
1962 return;
1963
1964 ret = libevdev_uinput_write_event(d->uinput, type, code, value);
1965 litest_assert_int_eq(ret, 0);
1966 }
1967
1968 static bool
axis_replacement_value(struct litest_device * d,struct axis_replacement * axes,int32_t evcode,int32_t * value)1969 axis_replacement_value(struct litest_device *d,
1970 struct axis_replacement *axes,
1971 int32_t evcode,
1972 int32_t *value)
1973 {
1974 struct axis_replacement *axis = axes;
1975
1976 if (!axes)
1977 return false;
1978
1979 while (axis->evcode != -1) {
1980 if (axis->evcode == evcode) {
1981 switch (evcode) {
1982 case ABS_MT_SLOT:
1983 case ABS_MT_TRACKING_ID:
1984 case ABS_MT_TOOL_TYPE:
1985 *value = axis->value;
1986 break;
1987 default:
1988 *value = litest_scale(d, evcode, axis->value);
1989 break;
1990 }
1991 return true;
1992 }
1993 axis++;
1994 }
1995
1996 return false;
1997 }
1998
1999 int
litest_auto_assign_value(struct litest_device * d,const struct input_event * ev,int slot,double x,double y,struct axis_replacement * axes,bool touching)2000 litest_auto_assign_value(struct litest_device *d,
2001 const struct input_event *ev,
2002 int slot, double x, double y,
2003 struct axis_replacement *axes,
2004 bool touching)
2005 {
2006 static int tracking_id;
2007 int value = ev->value;
2008
2009 if (value != LITEST_AUTO_ASSIGN || ev->type != EV_ABS)
2010 return value;
2011
2012 switch (ev->code) {
2013 case ABS_X:
2014 case ABS_MT_POSITION_X:
2015 value = litest_scale(d, ABS_X, x);
2016 break;
2017 case ABS_Y:
2018 case ABS_MT_POSITION_Y:
2019 value = litest_scale(d, ABS_Y, y);
2020 break;
2021 case ABS_MT_TRACKING_ID:
2022 value = ++tracking_id;
2023 break;
2024 case ABS_MT_SLOT:
2025 value = slot;
2026 break;
2027 case ABS_MT_DISTANCE:
2028 value = touching ? 0 : 1;
2029 break;
2030 case ABS_MT_TOOL_TYPE:
2031 if (!axis_replacement_value(d, axes, ev->code, &value))
2032 value = MT_TOOL_FINGER;
2033 break;
2034 default:
2035 if (!axis_replacement_value(d, axes, ev->code, &value) &&
2036 d->interface->get_axis_default) {
2037 int error = d->interface->get_axis_default(d,
2038 ev->code,
2039 &value);
2040 if (error) {
2041 litest_abort_msg("Failed to get default axis value for %s (%d)\n",
2042 libevdev_event_code_get_name(EV_ABS, ev->code),
2043 ev->code);
2044 }
2045 }
2046 break;
2047 }
2048
2049 return value;
2050 }
2051
2052 static void
send_btntool(struct litest_device * d,bool hover)2053 send_btntool(struct litest_device *d, bool hover)
2054 {
2055 litest_event(d, EV_KEY, BTN_TOUCH, d->ntouches_down != 0 && !hover);
2056 litest_event(d, EV_KEY, BTN_TOOL_FINGER, d->ntouches_down == 1);
2057 litest_event(d, EV_KEY, BTN_TOOL_DOUBLETAP, d->ntouches_down == 2);
2058 litest_event(d, EV_KEY, BTN_TOOL_TRIPLETAP, d->ntouches_down == 3);
2059 litest_event(d, EV_KEY, BTN_TOOL_QUADTAP, d->ntouches_down == 4);
2060 litest_event(d, EV_KEY, BTN_TOOL_QUINTTAP, d->ntouches_down == 5);
2061 }
2062
2063 static void
slot_start(struct litest_device * d,unsigned int slot,double x,double y,struct axis_replacement * axes,bool touching,bool filter_abs_xy)2064 slot_start(struct litest_device *d,
2065 unsigned int slot,
2066 double x,
2067 double y,
2068 struct axis_replacement *axes,
2069 bool touching,
2070 bool filter_abs_xy)
2071 {
2072 struct input_event *ev;
2073
2074 litest_assert_int_ge(d->ntouches_down, 0);
2075 d->ntouches_down++;
2076
2077 send_btntool(d, !touching);
2078
2079 /* If the test device overrides touch_down and says it didn't
2080 * handle the event, let's continue normally */
2081 if (d->interface->touch_down &&
2082 d->interface->touch_down(d, slot, x, y))
2083 return;
2084
2085 for (ev = d->interface->touch_down_events;
2086 ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
2087 ev++) {
2088 int value = litest_auto_assign_value(d,
2089 ev,
2090 slot,
2091 x,
2092 y,
2093 axes,
2094 touching);
2095 if (value == LITEST_AUTO_ASSIGN)
2096 continue;
2097
2098 if (filter_abs_xy && ev->type == EV_ABS &&
2099 (ev->code == ABS_X || ev->code == ABS_Y))
2100 continue;
2101
2102 litest_event(d, ev->type, ev->code, value);
2103 }
2104 }
2105
2106 static void
slot_move(struct litest_device * d,unsigned int slot,double x,double y,struct axis_replacement * axes,bool touching,bool filter_abs_xy)2107 slot_move(struct litest_device *d,
2108 unsigned int slot,
2109 double x,
2110 double y,
2111 struct axis_replacement *axes,
2112 bool touching,
2113 bool filter_abs_xy)
2114 {
2115 struct input_event *ev;
2116
2117 if (d->interface->touch_move &&
2118 d->interface->touch_move(d, slot, x, y))
2119 return;
2120
2121 for (ev = d->interface->touch_move_events;
2122 ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
2123 ev++) {
2124 int value = litest_auto_assign_value(d,
2125 ev,
2126 slot,
2127 x,
2128 y,
2129 axes,
2130 touching);
2131 if (value == LITEST_AUTO_ASSIGN)
2132 continue;
2133
2134 if (filter_abs_xy && ev->type == EV_ABS &&
2135 (ev->code == ABS_X || ev->code == ABS_Y))
2136 continue;
2137
2138 litest_event(d, ev->type, ev->code, value);
2139 }
2140 }
2141
2142 static void
touch_up(struct litest_device * d,unsigned int slot)2143 touch_up(struct litest_device *d, unsigned int slot)
2144 {
2145 struct input_event *ev;
2146 struct input_event up[] = {
2147 { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
2148 { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
2149 { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = 0 },
2150 { .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = 0 },
2151 { .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = 0 },
2152 { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
2153 { .type = -1, .code = -1 }
2154 };
2155
2156 litest_assert_int_gt(d->ntouches_down, 0);
2157 d->ntouches_down--;
2158
2159 send_btntool(d, false);
2160
2161 if (d->interface->touch_up &&
2162 d->interface->touch_up(d, slot)) {
2163 return;
2164 } else if (d->interface->touch_up_events) {
2165 ev = d->interface->touch_up_events;
2166 } else
2167 ev = up;
2168
2169 for ( /* */;
2170 ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
2171 ev++) {
2172 int value = litest_auto_assign_value(d,
2173 ev,
2174 slot,
2175 0,
2176 0,
2177 NULL,
2178 false);
2179 litest_event(d, ev->type, ev->code, value);
2180 }
2181 }
2182
2183 static void
litest_slot_start(struct litest_device * d,unsigned int slot,double x,double y,struct axis_replacement * axes,bool touching)2184 litest_slot_start(struct litest_device *d,
2185 unsigned int slot,
2186 double x,
2187 double y,
2188 struct axis_replacement *axes,
2189 bool touching)
2190 {
2191 double t, l, r = 0, b = 0; /* top, left, right, bottom */
2192 bool filter_abs_xy = false;
2193
2194 if (!d->semi_mt.is_semi_mt) {
2195 slot_start(d, slot, x, y, axes, touching, filter_abs_xy);
2196 return;
2197 }
2198
2199 if (d->ntouches_down >= 2 || slot > 1)
2200 return;
2201
2202 slot = d->ntouches_down;
2203
2204 if (d->ntouches_down == 0) {
2205 l = x;
2206 t = y;
2207 } else {
2208 int other = (slot + 1) % 2;
2209 l = min(x, d->semi_mt.touches[other].x);
2210 t = min(y, d->semi_mt.touches[other].y);
2211 r = max(x, d->semi_mt.touches[other].x);
2212 b = max(y, d->semi_mt.touches[other].y);
2213 }
2214
2215 litest_push_event_frame(d);
2216 if (d->ntouches_down == 0)
2217 slot_start(d, 0, l, t, axes, touching, filter_abs_xy);
2218 else
2219 slot_move(d, 0, l, t, axes, touching, filter_abs_xy);
2220
2221 if (slot == 1) {
2222 filter_abs_xy = true;
2223 slot_start(d, 1, r, b, axes, touching, filter_abs_xy);
2224 }
2225
2226 litest_pop_event_frame(d);
2227
2228 d->semi_mt.touches[slot].x = x;
2229 d->semi_mt.touches[slot].y = y;
2230 }
2231
2232 void
litest_touch_sequence(struct litest_device * d,unsigned int slot,double x_from,double y_from,double x_to,double y_to,int steps)2233 litest_touch_sequence(struct litest_device *d,
2234 unsigned int slot,
2235 double x_from,
2236 double y_from,
2237 double x_to,
2238 double y_to,
2239 int steps)
2240 {
2241 litest_touch_down(d, slot, x_from, y_from);
2242 litest_touch_move_to(d, slot,
2243 x_from, y_from,
2244 x_to, y_to,
2245 steps);
2246 litest_touch_up(d, slot);
2247 }
2248
2249 void
litest_touch_down(struct litest_device * d,unsigned int slot,double x,double y)2250 litest_touch_down(struct litest_device *d,
2251 unsigned int slot,
2252 double x,
2253 double y)
2254 {
2255 litest_slot_start(d, slot, x, y, NULL, true);
2256 }
2257
2258 void
litest_touch_down_extended(struct litest_device * d,unsigned int slot,double x,double y,struct axis_replacement * axes)2259 litest_touch_down_extended(struct litest_device *d,
2260 unsigned int slot,
2261 double x,
2262 double y,
2263 struct axis_replacement *axes)
2264 {
2265 litest_slot_start(d, slot, x, y, axes, true);
2266 }
2267
2268 static void
litest_slot_move(struct litest_device * d,unsigned int slot,double x,double y,struct axis_replacement * axes,bool touching)2269 litest_slot_move(struct litest_device *d,
2270 unsigned int slot,
2271 double x,
2272 double y,
2273 struct axis_replacement *axes,
2274 bool touching)
2275 {
2276 double t, l, r = 0, b = 0; /* top, left, right, bottom */
2277 bool filter_abs_xy = false;
2278
2279 if (!d->semi_mt.is_semi_mt) {
2280 slot_move(d, slot, x, y, axes, touching, filter_abs_xy);
2281 return;
2282 }
2283
2284 if (d->ntouches_down > 2 || slot > 1)
2285 return;
2286
2287 if (d->ntouches_down == 1) {
2288 l = x;
2289 t = y;
2290 } else {
2291 int other = (slot + 1) % 2;
2292 l = min(x, d->semi_mt.touches[other].x);
2293 t = min(y, d->semi_mt.touches[other].y);
2294 r = max(x, d->semi_mt.touches[other].x);
2295 b = max(y, d->semi_mt.touches[other].y);
2296 }
2297
2298 litest_push_event_frame(d);
2299 slot_move(d, 0, l, t, axes, touching, filter_abs_xy);
2300
2301 if (d->ntouches_down == 2) {
2302 filter_abs_xy = true;
2303 slot_move(d, 1, r, b, axes, touching, filter_abs_xy);
2304 }
2305
2306 litest_pop_event_frame(d);
2307
2308 d->semi_mt.touches[slot].x = x;
2309 d->semi_mt.touches[slot].y = y;
2310 }
2311
2312 void
litest_touch_up(struct litest_device * d,unsigned int slot)2313 litest_touch_up(struct litest_device *d, unsigned int slot)
2314 {
2315 if (!d->semi_mt.is_semi_mt) {
2316 touch_up(d, slot);
2317 return;
2318 }
2319
2320 if (d->ntouches_down > 2 || slot > 1)
2321 return;
2322
2323 litest_push_event_frame(d);
2324 touch_up(d, d->ntouches_down - 1);
2325
2326 /* if we have one finger left, send x/y coords for that finger left.
2327 this is likely to happen with a real touchpad */
2328 if (d->ntouches_down == 1) {
2329 bool touching = true;
2330 bool filter_abs_xy = false;
2331
2332 int other = (slot + 1) % 2;
2333 slot_move(d,
2334 0,
2335 d->semi_mt.touches[other].x,
2336 d->semi_mt.touches[other].y,
2337 NULL,
2338 touching,
2339 filter_abs_xy);
2340 }
2341
2342 litest_pop_event_frame(d);
2343 }
2344
2345 void
litest_touch_move(struct litest_device * d,unsigned int slot,double x,double y)2346 litest_touch_move(struct litest_device *d,
2347 unsigned int slot,
2348 double x,
2349 double y)
2350 {
2351 litest_slot_move(d, slot, x, y, NULL, true);
2352 }
2353
2354 void
litest_touch_move_extended(struct litest_device * d,unsigned int slot,double x,double y,struct axis_replacement * axes)2355 litest_touch_move_extended(struct litest_device *d,
2356 unsigned int slot,
2357 double x,
2358 double y,
2359 struct axis_replacement *axes)
2360 {
2361 litest_slot_move(d, slot, x, y, axes, true);
2362 }
2363
2364 void
litest_touch_move_to(struct litest_device * d,unsigned int slot,double x_from,double y_from,double x_to,double y_to,int steps)2365 litest_touch_move_to(struct litest_device *d,
2366 unsigned int slot,
2367 double x_from, double y_from,
2368 double x_to, double y_to,
2369 int steps)
2370 {
2371 litest_touch_move_to_extended(d, slot,
2372 x_from, y_from,
2373 x_to, y_to,
2374 NULL,
2375 steps);
2376 }
2377
2378 void
litest_touch_move_to_extended(struct litest_device * d,unsigned int slot,double x_from,double y_from,double x_to,double y_to,struct axis_replacement * axes,int steps)2379 litest_touch_move_to_extended(struct litest_device *d,
2380 unsigned int slot,
2381 double x_from, double y_from,
2382 double x_to, double y_to,
2383 struct axis_replacement *axes,
2384 int steps)
2385 {
2386 int sleep_ms = 10;
2387
2388 for (int i = 1; i < steps; i++) {
2389 litest_touch_move_extended(d, slot,
2390 x_from + (x_to - x_from)/steps * i,
2391 y_from + (y_to - y_from)/steps * i,
2392 axes);
2393 libinput_dispatch(d->libinput);
2394 msleep(sleep_ms);
2395 libinput_dispatch(d->libinput);
2396 }
2397 litest_touch_move_extended(d, slot, x_to, y_to, axes);
2398 }
2399
2400 static int
auto_assign_tablet_value(struct litest_device * d,const struct input_event * ev,int x,int y,struct axis_replacement * axes)2401 auto_assign_tablet_value(struct litest_device *d,
2402 const struct input_event *ev,
2403 int x, int y,
2404 struct axis_replacement *axes)
2405 {
2406 static int tracking_id;
2407 int value = ev->value;
2408
2409 if (value != LITEST_AUTO_ASSIGN || ev->type != EV_ABS)
2410 return value;
2411
2412 switch (ev->code) {
2413 case ABS_MT_TRACKING_ID:
2414 value = ++tracking_id;
2415 break;
2416 case ABS_X:
2417 case ABS_MT_POSITION_X:
2418 value = litest_scale(d, ABS_X, x);
2419 break;
2420 case ABS_Y:
2421 case ABS_MT_POSITION_Y:
2422 value = litest_scale(d, ABS_Y, y);
2423 break;
2424 default:
2425 if (!axis_replacement_value(d, axes, ev->code, &value) &&
2426 d->interface->get_axis_default) {
2427 int error = d->interface->get_axis_default(d, ev->code, &value);
2428 if (error) {
2429 litest_abort_msg("Failed to get default axis value for %s (%d)\n",
2430 libevdev_event_code_get_name(EV_ABS, ev->code),
2431 ev->code);
2432 }
2433 }
2434 break;
2435 }
2436
2437 return value;
2438 }
2439
2440 static int
tablet_ignore_event(const struct input_event * ev,int value)2441 tablet_ignore_event(const struct input_event *ev, int value)
2442 {
2443 return value == -1 && (ev->code == ABS_PRESSURE || ev->code == ABS_DISTANCE);
2444 }
2445
2446 void
litest_tablet_proximity_in(struct litest_device * d,int x,int y,struct axis_replacement * axes)2447 litest_tablet_proximity_in(struct litest_device *d, int x, int y, struct axis_replacement *axes)
2448 {
2449 struct input_event *ev;
2450
2451 ev = d->interface->tablet_proximity_in_events;
2452 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2453 int value = auto_assign_tablet_value(d, ev, x, y, axes);
2454 if (!tablet_ignore_event(ev, value))
2455 litest_event(d, ev->type, ev->code, value);
2456 ev++;
2457 }
2458 }
2459
2460 void
litest_tablet_proximity_out(struct litest_device * d)2461 litest_tablet_proximity_out(struct litest_device *d)
2462 {
2463 struct input_event *ev;
2464
2465 ev = d->interface->tablet_proximity_out_events;
2466 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2467 int value = auto_assign_tablet_value(d, ev, -1, -1, NULL);
2468 if (!tablet_ignore_event(ev, value))
2469 litest_event(d, ev->type, ev->code, value);
2470 ev++;
2471 }
2472 }
2473
2474 void
litest_tablet_motion(struct litest_device * d,int x,int y,struct axis_replacement * axes)2475 litest_tablet_motion(struct litest_device *d, int x, int y, struct axis_replacement *axes)
2476 {
2477 struct input_event *ev;
2478
2479 ev = d->interface->tablet_motion_events;
2480 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2481 int value = auto_assign_tablet_value(d, ev, x, y, axes);
2482 if (!tablet_ignore_event(ev, value))
2483 litest_event(d, ev->type, ev->code, value);
2484 ev++;
2485 }
2486 }
2487
2488 void
litest_touch_move_two_touches(struct litest_device * d,double x0,double y0,double x1,double y1,double dx,double dy,int steps)2489 litest_touch_move_two_touches(struct litest_device *d,
2490 double x0, double y0,
2491 double x1, double y1,
2492 double dx, double dy,
2493 int steps)
2494 {
2495 int sleep_ms = 10;
2496
2497 for (int i = 1; i < steps; i++) {
2498 litest_push_event_frame(d);
2499 litest_touch_move(d, 0, x0 + dx / steps * i,
2500 y0 + dy / steps * i);
2501 litest_touch_move(d, 1, x1 + dx / steps * i,
2502 y1 + dy / steps * i);
2503 litest_pop_event_frame(d);
2504 libinput_dispatch(d->libinput);
2505 msleep(sleep_ms);
2506 libinput_dispatch(d->libinput);
2507 }
2508 litest_push_event_frame(d);
2509 litest_touch_move(d, 0, x0 + dx, y0 + dy);
2510 litest_touch_move(d, 1, x1 + dx, y1 + dy);
2511 litest_pop_event_frame(d);
2512 }
2513
2514 void
litest_touch_move_three_touches(struct litest_device * d,double x0,double y0,double x1,double y1,double x2,double y2,double dx,double dy,int steps)2515 litest_touch_move_three_touches(struct litest_device *d,
2516 double x0, double y0,
2517 double x1, double y1,
2518 double x2, double y2,
2519 double dx, double dy,
2520 int steps)
2521 {
2522 int sleep_ms = 10;
2523
2524 for (int i = 0; i < steps - 1; i++) {
2525 litest_touch_move(d, 0, x0 + dx / steps * i,
2526 y0 + dy / steps * i);
2527 litest_touch_move(d, 1, x1 + dx / steps * i,
2528 y1 + dy / steps * i);
2529 litest_touch_move(d, 2, x2 + dx / steps * i,
2530 y2 + dy / steps * i);
2531
2532 libinput_dispatch(d->libinput);
2533 msleep(sleep_ms);
2534 libinput_dispatch(d->libinput);
2535 }
2536 litest_touch_move(d, 0, x0 + dx, y0 + dy);
2537 litest_touch_move(d, 1, x1 + dx, y1 + dy);
2538 litest_touch_move(d, 2, x2 + dx, y2 + dy);
2539 }
2540
2541 void
litest_hover_start(struct litest_device * d,unsigned int slot,double x,double y)2542 litest_hover_start(struct litest_device *d,
2543 unsigned int slot,
2544 double x,
2545 double y)
2546 {
2547 struct axis_replacement axes[] = {
2548 {ABS_MT_PRESSURE, 0 },
2549 {ABS_PRESSURE, 0 },
2550 {-1, -1 },
2551 };
2552
2553 litest_slot_start(d, slot, x, y, axes, 0);
2554 }
2555
2556 void
litest_hover_end(struct litest_device * d,unsigned int slot)2557 litest_hover_end(struct litest_device *d, unsigned int slot)
2558 {
2559 struct input_event *ev;
2560 struct input_event up[] = {
2561 { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
2562 { .type = EV_ABS, .code = ABS_MT_DISTANCE, .value = 1 },
2563 { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
2564 { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
2565 { .type = -1, .code = -1 }
2566 };
2567
2568 litest_assert_int_gt(d->ntouches_down, 0);
2569 d->ntouches_down--;
2570
2571 send_btntool(d, true);
2572
2573 if (d->interface->touch_up) {
2574 d->interface->touch_up(d, slot);
2575 return;
2576 } else if (d->interface->touch_up_events) {
2577 ev = d->interface->touch_up_events;
2578 } else
2579 ev = up;
2580
2581 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2582 int value = litest_auto_assign_value(d, ev, slot, 0, 0, NULL, false);
2583 litest_event(d, ev->type, ev->code, value);
2584 ev++;
2585 }
2586 }
2587
2588 void
litest_hover_move(struct litest_device * d,unsigned int slot,double x,double y)2589 litest_hover_move(struct litest_device *d, unsigned int slot,
2590 double x, double y)
2591 {
2592 struct axis_replacement axes[] = {
2593 {ABS_MT_PRESSURE, 0 },
2594 {ABS_PRESSURE, 0 },
2595 {-1, -1 },
2596 };
2597
2598 litest_slot_move(d, slot, x, y, axes, false);
2599 }
2600
2601 void
litest_hover_move_to(struct litest_device * d,unsigned int slot,double x_from,double y_from,double x_to,double y_to,int steps)2602 litest_hover_move_to(struct litest_device *d,
2603 unsigned int slot,
2604 double x_from, double y_from,
2605 double x_to, double y_to,
2606 int steps)
2607 {
2608 int sleep_ms = 10;
2609
2610 for (int i = 0; i < steps - 1; i++) {
2611 litest_hover_move(d, slot,
2612 x_from + (x_to - x_from)/steps * i,
2613 y_from + (y_to - y_from)/steps * i);
2614 libinput_dispatch(d->libinput);
2615 msleep(sleep_ms);
2616 libinput_dispatch(d->libinput);
2617 }
2618 litest_hover_move(d, slot, x_to, y_to);
2619 }
2620
2621 void
litest_hover_move_two_touches(struct litest_device * d,double x0,double y0,double x1,double y1,double dx,double dy,int steps)2622 litest_hover_move_two_touches(struct litest_device *d,
2623 double x0, double y0,
2624 double x1, double y1,
2625 double dx, double dy,
2626 int steps)
2627 {
2628 int sleep_ms = 10;
2629
2630 for (int i = 0; i < steps - 1; i++) {
2631 litest_push_event_frame(d);
2632 litest_hover_move(d, 0, x0 + dx / steps * i,
2633 y0 + dy / steps * i);
2634 litest_hover_move(d, 1, x1 + dx / steps * i,
2635 y1 + dy / steps * i);
2636 litest_pop_event_frame(d);
2637 libinput_dispatch(d->libinput);
2638 msleep(sleep_ms);
2639 libinput_dispatch(d->libinput);
2640 }
2641 litest_push_event_frame(d);
2642 litest_hover_move(d, 0, x0 + dx, y0 + dy);
2643 litest_hover_move(d, 1, x1 + dx, y1 + dy);
2644 litest_pop_event_frame(d);
2645 }
2646
2647 void
litest_button_click(struct litest_device * d,unsigned int button,bool is_press)2648 litest_button_click(struct litest_device *d,
2649 unsigned int button,
2650 bool is_press)
2651 {
2652 struct input_event *ev;
2653 struct input_event click[] = {
2654 { .type = EV_KEY, .code = button, .value = is_press ? 1 : 0 },
2655 { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
2656 };
2657
2658 ARRAY_FOR_EACH(click, ev)
2659 litest_event(d, ev->type, ev->code, ev->value);
2660 }
2661
2662 void
litest_button_click_debounced(struct litest_device * d,struct libinput * li,unsigned int button,bool is_press)2663 litest_button_click_debounced(struct litest_device *d,
2664 struct libinput *li,
2665 unsigned int button,
2666 bool is_press)
2667 {
2668 litest_button_click(d, button, is_press);
2669
2670 libinput_dispatch(li);
2671 litest_timeout_debounce();
2672 libinput_dispatch(li);
2673 }
2674
2675 void
litest_button_scroll(struct litest_device * dev,unsigned int button,double dx,double dy)2676 litest_button_scroll(struct litest_device *dev,
2677 unsigned int button,
2678 double dx, double dy)
2679 {
2680 struct libinput *li = dev->libinput;
2681
2682 litest_button_click_debounced(dev, li, button, 1);
2683
2684 libinput_dispatch(li);
2685 litest_timeout_buttonscroll();
2686 libinput_dispatch(li);
2687
2688 litest_event(dev, EV_REL, REL_X, dx);
2689 litest_event(dev, EV_REL, REL_Y, dy);
2690 litest_event(dev, EV_SYN, SYN_REPORT, 0);
2691
2692 litest_button_click_debounced(dev, li, button, 0);
2693
2694 libinput_dispatch(li);
2695 }
2696
2697 void
litest_button_scroll_locked(struct litest_device * dev,unsigned int button,double dx,double dy)2698 litest_button_scroll_locked(struct litest_device *dev,
2699 unsigned int button,
2700 double dx, double dy)
2701 {
2702 struct libinput *li = dev->libinput;
2703
2704 litest_button_click_debounced(dev, li, button, 1);
2705 litest_button_click_debounced(dev, li, button, 0);
2706
2707 libinput_dispatch(li);
2708 litest_timeout_buttonscroll();
2709 libinput_dispatch(li);
2710
2711 litest_event(dev, EV_REL, REL_X, dx);
2712 litest_event(dev, EV_REL, REL_Y, dy);
2713 litest_event(dev, EV_SYN, SYN_REPORT, 0);
2714
2715 libinput_dispatch(li);
2716 }
2717
2718 void
litest_keyboard_key(struct litest_device * d,unsigned int key,bool is_press)2719 litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press)
2720 {
2721 struct input_event *ev;
2722 struct input_event click[] = {
2723 { .type = EV_KEY, .code = key, .value = is_press ? 1 : 0 },
2724 { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
2725 };
2726
2727 ARRAY_FOR_EACH(click, ev)
2728 litest_event(d, ev->type, ev->code, ev->value);
2729 }
2730
2731 void
litest_switch_action(struct litest_device * dev,enum libinput_switch sw,enum libinput_switch_state state)2732 litest_switch_action(struct litest_device *dev,
2733 enum libinput_switch sw,
2734 enum libinput_switch_state state)
2735 {
2736 unsigned int code;
2737
2738 switch (sw) {
2739 case LIBINPUT_SWITCH_LID:
2740 code = SW_LID;
2741 break;
2742 case LIBINPUT_SWITCH_TABLET_MODE:
2743 code = SW_TABLET_MODE;
2744 break;
2745 default:
2746 litest_abort_msg("Invalid switch %d", sw);
2747 break;
2748 }
2749 litest_event(dev, EV_SW, code, state);
2750 litest_event(dev, EV_SYN, SYN_REPORT, 0);
2751 }
2752
2753 static int
litest_scale_axis(const struct litest_device * d,unsigned int axis,double val)2754 litest_scale_axis(const struct litest_device *d,
2755 unsigned int axis,
2756 double val)
2757 {
2758 const struct input_absinfo *abs;
2759
2760 litest_assert_double_ge(val, 0.0);
2761 /* major/minor must be able to beyond 100% for large fingers */
2762 if (axis != ABS_MT_TOUCH_MAJOR &&
2763 axis != ABS_MT_TOUCH_MINOR) {
2764 litest_assert_double_le(val, 100.0);
2765 }
2766
2767 abs = libevdev_get_abs_info(d->evdev, axis);
2768 litest_assert_notnull(abs);
2769
2770 return (abs->maximum - abs->minimum) * val/100.0 + abs->minimum;
2771 }
2772
2773 static inline int
litest_scale_range(int min,int max,double val)2774 litest_scale_range(int min, int max, double val)
2775 {
2776 litest_assert_int_ge((int)val, 0);
2777 litest_assert_int_le((int)val, 100);
2778
2779 return (max - min) * val/100.0 + min;
2780 }
2781
2782 int
litest_scale(const struct litest_device * d,unsigned int axis,double val)2783 litest_scale(const struct litest_device *d, unsigned int axis, double val)
2784 {
2785 int min, max;
2786
2787 litest_assert_double_ge(val, 0.0);
2788 /* major/minor must be able to beyond 100% for large fingers */
2789 if (axis != ABS_MT_TOUCH_MAJOR &&
2790 axis != ABS_MT_TOUCH_MINOR)
2791 litest_assert_double_le(val, 100.0);
2792
2793 if (axis <= ABS_Y) {
2794 min = d->interface->min[axis];
2795 max = d->interface->max[axis];
2796
2797 return litest_scale_range(min, max, val);
2798 } else {
2799 return litest_scale_axis(d, axis, val);
2800 }
2801 }
2802
2803 static inline int
auto_assign_pad_value(struct litest_device * dev,struct input_event * ev,double value)2804 auto_assign_pad_value(struct litest_device *dev,
2805 struct input_event *ev,
2806 double value)
2807 {
2808 const struct input_absinfo *abs;
2809
2810 if (ev->value != LITEST_AUTO_ASSIGN ||
2811 ev->type != EV_ABS)
2812 return value;
2813
2814 abs = libevdev_get_abs_info(dev->evdev, ev->code);
2815 litest_assert_notnull(abs);
2816
2817 if (ev->code == ABS_RX || ev->code == ABS_RY) {
2818 double min = abs->minimum != 0 ? log2(abs->minimum) : 0,
2819 max = abs->maximum != 0 ? log2(abs->maximum) : 0;
2820
2821 /* Value 0 is reserved for finger up, so a value of 0% is
2822 * actually 1 */
2823 if (value == 0.0) {
2824 return 1;
2825 } else {
2826 value = litest_scale_range(min, max, value);
2827 return pow(2, value);
2828 }
2829 } else {
2830 return litest_scale_range(abs->minimum, abs->maximum, value);
2831 }
2832 }
2833
2834 void
litest_pad_ring_start(struct litest_device * d,double value)2835 litest_pad_ring_start(struct litest_device *d, double value)
2836 {
2837 struct input_event *ev;
2838
2839 ev = d->interface->pad_ring_start_events;
2840 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2841 value = auto_assign_pad_value(d, ev, value);
2842 litest_event(d, ev->type, ev->code, value);
2843 ev++;
2844 }
2845 }
2846
2847 void
litest_pad_ring_change(struct litest_device * d,double value)2848 litest_pad_ring_change(struct litest_device *d, double value)
2849 {
2850 struct input_event *ev;
2851
2852 ev = d->interface->pad_ring_change_events;
2853 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2854 value = auto_assign_pad_value(d, ev, value);
2855 litest_event(d, ev->type, ev->code, value);
2856 ev++;
2857 }
2858 }
2859
2860 void
litest_pad_ring_end(struct litest_device * d)2861 litest_pad_ring_end(struct litest_device *d)
2862 {
2863 struct input_event *ev;
2864
2865 ev = d->interface->pad_ring_end_events;
2866 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2867 litest_event(d, ev->type, ev->code, ev->value);
2868 ev++;
2869 }
2870 }
2871
2872 void
litest_pad_strip_start(struct litest_device * d,double value)2873 litest_pad_strip_start(struct litest_device *d, double value)
2874 {
2875 struct input_event *ev;
2876
2877 ev = d->interface->pad_strip_start_events;
2878 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2879 value = auto_assign_pad_value(d, ev, value);
2880 litest_event(d, ev->type, ev->code, value);
2881 ev++;
2882 }
2883 }
2884
2885 void
litest_pad_strip_change(struct litest_device * d,double value)2886 litest_pad_strip_change(struct litest_device *d, double value)
2887 {
2888 struct input_event *ev;
2889
2890 ev = d->interface->pad_strip_change_events;
2891 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2892 value = auto_assign_pad_value(d, ev, value);
2893 litest_event(d, ev->type, ev->code, value);
2894 ev++;
2895 }
2896 }
2897
2898 void
litest_pad_strip_end(struct litest_device * d)2899 litest_pad_strip_end(struct litest_device *d)
2900 {
2901 struct input_event *ev;
2902
2903 ev = d->interface->pad_strip_end_events;
2904 while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2905 litest_event(d, ev->type, ev->code, ev->value);
2906 ev++;
2907 }
2908 }
2909
2910 void
litest_wait_for_event(struct libinput * li)2911 litest_wait_for_event(struct libinput *li)
2912 {
2913 return litest_wait_for_event_of_type(li, -1);
2914 }
2915
2916 void
litest_wait_for_event_of_type(struct libinput * li,...)2917 litest_wait_for_event_of_type(struct libinput *li, ...)
2918 {
2919 va_list args;
2920 enum libinput_event_type types[32] = {LIBINPUT_EVENT_NONE};
2921 size_t ntypes = 0;
2922 enum libinput_event_type type;
2923 struct pollfd fds;
2924
2925 va_start(args, li);
2926 type = va_arg(args, int);
2927 while ((int)type != -1) {
2928 litest_assert_int_gt(type, 0U);
2929 litest_assert_int_lt(ntypes, ARRAY_LENGTH(types));
2930 types[ntypes++] = type;
2931 type = va_arg(args, int);
2932 }
2933 va_end(args);
2934
2935 fds.fd = libinput_get_fd(li);
2936 fds.events = POLLIN;
2937 fds.revents = 0;
2938
2939 while (1) {
2940 size_t i;
2941 struct libinput_event *event;
2942
2943 while ((type = libinput_next_event_type(li)) == LIBINPUT_EVENT_NONE) {
2944 int rc = poll(&fds, 1, 2000);
2945 litest_assert_int_gt(rc, 0);
2946 libinput_dispatch(li);
2947 }
2948
2949 /* no event mask means wait for any event */
2950 if (ntypes == 0)
2951 return;
2952
2953 for (i = 0; i < ntypes; i++) {
2954 if (type == types[i])
2955 return;
2956 }
2957
2958 event = libinput_get_event(li);
2959 libinput_event_destroy(event);
2960 }
2961 }
2962
2963 void
litest_drain_events(struct libinput * li)2964 litest_drain_events(struct libinput *li)
2965 {
2966 struct libinput_event *event;
2967
2968 libinput_dispatch(li);
2969 while ((event = libinput_get_event(li))) {
2970 libinput_event_destroy(event);
2971 libinput_dispatch(li);
2972 }
2973 }
2974
2975
2976 void
litest_drain_events_of_type(struct libinput * li,...)2977 litest_drain_events_of_type(struct libinput *li, ...)
2978 {
2979 enum libinput_event_type type;
2980 enum libinput_event_type types[32] = {LIBINPUT_EVENT_NONE};
2981 size_t ntypes = 0;
2982 va_list args;
2983
2984 va_start(args, li);
2985 type = va_arg(args, int);
2986 while ((int)type != -1) {
2987 litest_assert_int_gt(type, 0U);
2988 litest_assert_int_lt(ntypes, ARRAY_LENGTH(types));
2989 types[ntypes++] = type;
2990 type = va_arg(args, int);
2991 }
2992 va_end(args);
2993
2994 libinput_dispatch(li);
2995 type = libinput_next_event_type(li);
2996 while (type != LIBINPUT_EVENT_NONE) {
2997 struct libinput_event *event;
2998 bool found = false;
2999
3000 type = libinput_next_event_type(li);
3001
3002 for (size_t i = 0; i < ntypes; i++) {
3003 if (type == types[i]) {
3004 found = true;
3005 break;
3006 }
3007 }
3008 if (!found)
3009 return;
3010
3011 event = libinput_get_event(li);
3012 libinput_event_destroy(event);
3013 libinput_dispatch(li);
3014 }
3015 }
3016
3017 static const char *
litest_event_type_str(enum libinput_event_type type)3018 litest_event_type_str(enum libinput_event_type type)
3019 {
3020 const char *str = NULL;
3021
3022 switch (type) {
3023 case LIBINPUT_EVENT_NONE:
3024 abort();
3025 case LIBINPUT_EVENT_DEVICE_ADDED:
3026 str = "ADDED";
3027 break;
3028 case LIBINPUT_EVENT_DEVICE_REMOVED:
3029 str = "REMOVED";
3030 break;
3031 case LIBINPUT_EVENT_KEYBOARD_KEY:
3032 str = "KEY";
3033 break;
3034 case LIBINPUT_EVENT_POINTER_MOTION:
3035 str = "MOTION";
3036 break;
3037 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
3038 str = "ABSOLUTE";
3039 break;
3040 case LIBINPUT_EVENT_POINTER_BUTTON:
3041 str = "BUTTON";
3042 break;
3043 case LIBINPUT_EVENT_POINTER_AXIS:
3044 str = "AXIS";
3045 break;
3046 case LIBINPUT_EVENT_TOUCH_DOWN:
3047 str = "TOUCH DOWN";
3048 break;
3049 case LIBINPUT_EVENT_TOUCH_UP:
3050 str = "TOUCH UP";
3051 break;
3052 case LIBINPUT_EVENT_TOUCH_MOTION:
3053 str = "TOUCH MOTION";
3054 break;
3055 case LIBINPUT_EVENT_TOUCH_CANCEL:
3056 str = "TOUCH CANCEL";
3057 break;
3058 case LIBINPUT_EVENT_TOUCH_FRAME:
3059 str = "TOUCH FRAME";
3060 break;
3061 case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
3062 str = "GESTURE SWIPE START";
3063 break;
3064 case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
3065 str = "GESTURE SWIPE UPDATE";
3066 break;
3067 case LIBINPUT_EVENT_GESTURE_SWIPE_END:
3068 str = "GESTURE SWIPE END";
3069 break;
3070 case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
3071 str = "GESTURE PINCH START";
3072 break;
3073 case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
3074 str = "GESTURE PINCH UPDATE";
3075 break;
3076 case LIBINPUT_EVENT_GESTURE_PINCH_END:
3077 str = "GESTURE PINCH END";
3078 break;
3079 case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
3080 str = "TABLET TOOL AXIS";
3081 break;
3082 case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
3083 str = "TABLET TOOL PROX";
3084 break;
3085 case LIBINPUT_EVENT_TABLET_TOOL_TIP:
3086 str = "TABLET TOOL TIP";
3087 break;
3088 case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
3089 str = "TABLET TOOL BUTTON";
3090 break;
3091 case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
3092 str = "TABLET PAD BUTTON";
3093 break;
3094 case LIBINPUT_EVENT_TABLET_PAD_RING:
3095 str = "TABLET PAD RING";
3096 break;
3097 case LIBINPUT_EVENT_TABLET_PAD_STRIP:
3098 str = "TABLET PAD STRIP";
3099 break;
3100 case LIBINPUT_EVENT_TABLET_PAD_KEY:
3101 str = "TABLET PAD KEY";
3102 break;
3103 case LIBINPUT_EVENT_SWITCH_TOGGLE:
3104 str = "SWITCH TOGGLE";
3105 break;
3106 }
3107 return str;
3108 }
3109
3110 static const char *
litest_event_get_type_str(struct libinput_event * event)3111 litest_event_get_type_str(struct libinput_event *event)
3112 {
3113 return litest_event_type_str(libinput_event_get_type(event));
3114 }
3115
3116 static void
litest_print_event(struct libinput_event * event)3117 litest_print_event(struct libinput_event *event)
3118 {
3119 struct libinput_event_pointer *p;
3120 struct libinput_event_tablet_tool *t;
3121 struct libinput_event_tablet_pad *pad;
3122 struct libinput_device *dev;
3123 enum libinput_event_type type;
3124 double x, y;
3125
3126 dev = libinput_event_get_device(event);
3127 type = libinput_event_get_type(event);
3128
3129 fprintf(stderr,
3130 "device %s (%s) type %s ",
3131 libinput_device_get_sysname(dev),
3132 libinput_device_get_name(dev),
3133 litest_event_get_type_str(event));
3134 switch (type) {
3135 case LIBINPUT_EVENT_POINTER_MOTION:
3136 p = libinput_event_get_pointer_event(event);
3137 x = libinput_event_pointer_get_dx(p);
3138 y = libinput_event_pointer_get_dy(p);
3139 fprintf(stderr, "%.2f/%.2f", x, y);
3140 break;
3141 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
3142 p = libinput_event_get_pointer_event(event);
3143 x = libinput_event_pointer_get_absolute_x(p);
3144 y = libinput_event_pointer_get_absolute_y(p);
3145 fprintf(stderr, "%.2f/%.2f", x, y);
3146 break;
3147 case LIBINPUT_EVENT_POINTER_BUTTON:
3148 p = libinput_event_get_pointer_event(event);
3149 fprintf(stderr,
3150 "button %d state %d",
3151 libinput_event_pointer_get_button(p),
3152 libinput_event_pointer_get_button_state(p));
3153 break;
3154 case LIBINPUT_EVENT_POINTER_AXIS:
3155 p = libinput_event_get_pointer_event(event);
3156 x = 0.0;
3157 y = 0.0;
3158 if (libinput_event_pointer_has_axis(p,
3159 LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
3160 y = libinput_event_pointer_get_axis_value(p,
3161 LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
3162 if (libinput_event_pointer_has_axis(p,
3163 LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
3164 x = libinput_event_pointer_get_axis_value(p,
3165 LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
3166 fprintf(stderr, "vert %.2f horiz %.2f", y, x);
3167 break;
3168 case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
3169 t = libinput_event_get_tablet_tool_event(event);
3170 fprintf(stderr, "proximity %d",
3171 libinput_event_tablet_tool_get_proximity_state(t));
3172 break;
3173 case LIBINPUT_EVENT_TABLET_TOOL_TIP:
3174 t = libinput_event_get_tablet_tool_event(event);
3175 fprintf(stderr, "tip %d",
3176 libinput_event_tablet_tool_get_tip_state(t));
3177 break;
3178 case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
3179 t = libinput_event_get_tablet_tool_event(event);
3180 fprintf(stderr, "button %d state %d",
3181 libinput_event_tablet_tool_get_button(t),
3182 libinput_event_tablet_tool_get_button_state(t));
3183 break;
3184 case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
3185 pad = libinput_event_get_tablet_pad_event(event);
3186 fprintf(stderr, "button %d state %d",
3187 libinput_event_tablet_pad_get_button_number(pad),
3188 libinput_event_tablet_pad_get_button_state(pad));
3189 break;
3190 case LIBINPUT_EVENT_TABLET_PAD_RING:
3191 pad = libinput_event_get_tablet_pad_event(event);
3192 fprintf(stderr, "ring %d position %.2f source %d",
3193 libinput_event_tablet_pad_get_ring_number(pad),
3194 libinput_event_tablet_pad_get_ring_position(pad),
3195 libinput_event_tablet_pad_get_ring_source(pad));
3196 break;
3197 case LIBINPUT_EVENT_TABLET_PAD_STRIP:
3198 pad = libinput_event_get_tablet_pad_event(event);
3199 fprintf(stderr, "strip %d position %.2f source %d",
3200 libinput_event_tablet_pad_get_ring_number(pad),
3201 libinput_event_tablet_pad_get_ring_position(pad),
3202 libinput_event_tablet_pad_get_ring_source(pad));
3203 break;
3204 default:
3205 break;
3206 }
3207
3208 fprintf(stderr, "\n");
3209 }
3210
3211 void
litest_assert_event_type(struct libinput_event * event,enum libinput_event_type want)3212 litest_assert_event_type(struct libinput_event *event,
3213 enum libinput_event_type want)
3214 {
3215 if (libinput_event_get_type(event) == want)
3216 return;
3217
3218 fprintf(stderr,
3219 "FAILED EVENT TYPE: %s: have %s (%d) but want %s (%d)\n",
3220 libinput_device_get_name(libinput_event_get_device(event)),
3221 litest_event_get_type_str(event),
3222 libinput_event_get_type(event),
3223 litest_event_type_str(want),
3224 want);
3225 fprintf(stderr, "Wrong event is: ");
3226 litest_print_event(event);
3227 litest_backtrace();
3228 abort();
3229 }
3230
3231 void
litest_assert_empty_queue(struct libinput * li)3232 litest_assert_empty_queue(struct libinput *li)
3233 {
3234 bool empty_queue = true;
3235 struct libinput_event *event;
3236
3237 libinput_dispatch(li);
3238 while ((event = libinput_get_event(li))) {
3239 empty_queue = false;
3240 fprintf(stderr,
3241 "Unexpected event: ");
3242 litest_print_event(event);
3243 libinput_event_destroy(event);
3244 libinput_dispatch(li);
3245 }
3246
3247 litest_assert(empty_queue);
3248 }
3249
3250 static struct libevdev_uinput *
litest_create_uinput(const char * name,const struct input_id * id,const struct input_absinfo * abs_info,const int * events)3251 litest_create_uinput(const char *name,
3252 const struct input_id *id,
3253 const struct input_absinfo *abs_info,
3254 const int *events)
3255 {
3256 struct libevdev_uinput *uinput;
3257 struct libevdev *dev;
3258 int type, code;
3259 int rc, fd;
3260 const struct input_absinfo *abs;
3261 const struct input_absinfo default_abs = {
3262 .value = 0,
3263 .minimum = 0,
3264 .maximum = 100,
3265 .fuzz = 0,
3266 .flat = 0,
3267 .resolution = 100
3268 };
3269 char buf[512];
3270 const char *devnode;
3271
3272 dev = libevdev_new();
3273 litest_assert_ptr_notnull(dev);
3274
3275 snprintf(buf, sizeof(buf), "litest %s", name);
3276 libevdev_set_name(dev, buf);
3277 if (id) {
3278 libevdev_set_id_bustype(dev, id->bustype);
3279 libevdev_set_id_vendor(dev, id->vendor);
3280 libevdev_set_id_product(dev, id->product);
3281 libevdev_set_id_version(dev, id->version);
3282 }
3283
3284 abs = abs_info;
3285 while (abs && abs->value != -1) {
3286 struct input_absinfo a = *abs;
3287
3288 /* abs_info->value is used for the code and may be outside
3289 of [min, max] */
3290 a.value = abs->minimum;
3291 rc = libevdev_enable_event_code(dev, EV_ABS, abs->value, &a);
3292 litest_assert_int_eq(rc, 0);
3293 abs++;
3294 }
3295
3296 while (events &&
3297 (type = *events++) != -1 &&
3298 (code = *events++) != -1) {
3299 if (type == INPUT_PROP_MAX) {
3300 rc = libevdev_enable_property(dev, code);
3301 } else {
3302 rc = libevdev_enable_event_code(dev, type, code,
3303 type == EV_ABS ? &default_abs : NULL);
3304 }
3305 litest_assert_int_eq(rc, 0);
3306 }
3307
3308 rc = libevdev_uinput_create_from_device(dev,
3309 LIBEVDEV_UINPUT_OPEN_MANAGED,
3310 &uinput);
3311 /* workaround for a bug in libevdev pre-1.3
3312 http://cgit.freedesktop.org/libevdev/commit/?id=debe9b030c8069cdf78307888ef3b65830b25122 */
3313 if (rc == -EBADF)
3314 rc = -EACCES;
3315 litest_assert_msg(rc == 0, "Failed to create uinput device: %s\n", strerror(-rc));
3316
3317 libevdev_free(dev);
3318
3319 devnode = libevdev_uinput_get_devnode(uinput);
3320 litest_assert_notnull(devnode);
3321 fd = open(devnode, O_RDONLY);
3322 litest_assert_int_gt(fd, -1);
3323 rc = libevdev_new_from_fd(fd, &dev);
3324 litest_assert_int_eq(rc, 0);
3325
3326 /* uinput before kernel 4.5 + libevdev 1.5.0 does not support
3327 * setting the resolution, so we set it afterwards. This is of
3328 * course racy as hell but the way we _generally_ use this function
3329 * by the time libinput uses the device, we're finished here.
3330 *
3331 * If you have kernel 4.5 and libevdev 1.5.0 or later, this code
3332 * just keeps the room warm.
3333 */
3334 abs = abs_info;
3335 while (abs && abs->value != -1) {
3336 if (abs->resolution != 0) {
3337 if (libevdev_get_abs_resolution(dev, abs->value) ==
3338 abs->resolution)
3339 break;
3340
3341 rc = libevdev_kernel_set_abs_info(dev,
3342 abs->value,
3343 abs);
3344 litest_assert_int_eq(rc, 0);
3345 }
3346 abs++;
3347 }
3348 close(fd);
3349 libevdev_free(dev);
3350
3351 return uinput;
3352 }
3353
3354 struct libevdev_uinput *
litest_create_uinput_device_from_description(const char * name,const struct input_id * id,const struct input_absinfo * abs_info,const int * events)3355 litest_create_uinput_device_from_description(const char *name,
3356 const struct input_id *id,
3357 const struct input_absinfo *abs_info,
3358 const int *events)
3359 {
3360 struct libevdev_uinput *uinput;
3361 const char *syspath;
3362 char path[PATH_MAX];
3363
3364 struct udev_monitor *udev_monitor;
3365 struct udev_device *udev_device;
3366
3367 udev_monitor = udev_setup_monitor();
3368
3369 uinput = litest_create_uinput(name, id, abs_info, events);
3370
3371 syspath = libevdev_uinput_get_syspath(uinput);
3372 snprintf(path, sizeof(path), "%s/event", syspath);
3373
3374 udev_device = udev_wait_for_device_event(udev_monitor, "add", path);
3375
3376 litest_assert(udev_device_get_property_value(udev_device, "ID_INPUT"));
3377
3378 udev_device_unref(udev_device);
3379 udev_monitor_unref(udev_monitor);
3380
3381 return uinput;
3382 }
3383
3384 static struct libevdev_uinput *
litest_create_uinput_abs_device_v(const char * name,struct input_id * id,const struct input_absinfo * abs,va_list args)3385 litest_create_uinput_abs_device_v(const char *name,
3386 struct input_id *id,
3387 const struct input_absinfo *abs,
3388 va_list args)
3389 {
3390 int events[KEY_MAX * 2 + 2]; /* increase this if not sufficient */
3391 int *event = events;
3392 int type, code;
3393
3394 while ((type = va_arg(args, int)) != -1 &&
3395 (code = va_arg(args, int)) != -1) {
3396 *event++ = type;
3397 *event++ = code;
3398 litest_assert(event < &events[ARRAY_LENGTH(events) - 2]);
3399 }
3400
3401 *event++ = -1;
3402 *event++ = -1;
3403
3404 return litest_create_uinput_device_from_description(name, id,
3405 abs, events);
3406 }
3407
3408 struct libevdev_uinput *
litest_create_uinput_abs_device(const char * name,struct input_id * id,const struct input_absinfo * abs,...)3409 litest_create_uinput_abs_device(const char *name,
3410 struct input_id *id,
3411 const struct input_absinfo *abs,
3412 ...)
3413 {
3414 struct libevdev_uinput *uinput;
3415 va_list args;
3416
3417 va_start(args, abs);
3418 uinput = litest_create_uinput_abs_device_v(name, id, abs, args);
3419 va_end(args);
3420
3421 return uinput;
3422 }
3423
3424 struct libevdev_uinput *
litest_create_uinput_device(const char * name,struct input_id * id,...)3425 litest_create_uinput_device(const char *name, struct input_id *id, ...)
3426 {
3427 struct libevdev_uinput *uinput;
3428 va_list args;
3429
3430 va_start(args, id);
3431 uinput = litest_create_uinput_abs_device_v(name, id, NULL, args);
3432 va_end(args);
3433
3434 return uinput;
3435 }
3436
3437 struct libinput_event_pointer*
litest_is_button_event(struct libinput_event * event,unsigned int button,enum libinput_button_state state)3438 litest_is_button_event(struct libinput_event *event,
3439 unsigned int button,
3440 enum libinput_button_state state)
3441 {
3442 struct libinput_event_pointer *ptrev;
3443 enum libinput_event_type type = LIBINPUT_EVENT_POINTER_BUTTON;
3444
3445 litest_assert_ptr_notnull(event);
3446 litest_assert_event_type(event, type);
3447 ptrev = libinput_event_get_pointer_event(event);
3448 litest_assert_int_eq(libinput_event_pointer_get_button(ptrev),
3449 button);
3450 litest_assert_int_eq(libinput_event_pointer_get_button_state(ptrev),
3451 state);
3452
3453 return ptrev;
3454 }
3455
3456 struct libinput_event_pointer *
litest_is_axis_event(struct libinput_event * event,enum libinput_pointer_axis axis,enum libinput_pointer_axis_source source)3457 litest_is_axis_event(struct libinput_event *event,
3458 enum libinput_pointer_axis axis,
3459 enum libinput_pointer_axis_source source)
3460 {
3461 struct libinput_event_pointer *ptrev;
3462 enum libinput_event_type type = LIBINPUT_EVENT_POINTER_AXIS;
3463
3464 litest_assert_ptr_notnull(event);
3465 litest_assert_event_type(event, type);
3466 ptrev = libinput_event_get_pointer_event(event);
3467 litest_assert(libinput_event_pointer_has_axis(ptrev, axis));
3468
3469 if (source != 0)
3470 litest_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
3471 source);
3472
3473 return ptrev;
3474 }
3475
3476 struct libinput_event_pointer *
litest_is_motion_event(struct libinput_event * event)3477 litest_is_motion_event(struct libinput_event *event)
3478 {
3479 struct libinput_event_pointer *ptrev;
3480 enum libinput_event_type type = LIBINPUT_EVENT_POINTER_MOTION;
3481 double x, y, ux, uy;
3482
3483 litest_assert_ptr_notnull(event);
3484 litest_assert_event_type(event, type);
3485 ptrev = libinput_event_get_pointer_event(event);
3486
3487 x = libinput_event_pointer_get_dx(ptrev);
3488 y = libinput_event_pointer_get_dy(ptrev);
3489 ux = libinput_event_pointer_get_dx_unaccelerated(ptrev);
3490 uy = libinput_event_pointer_get_dy_unaccelerated(ptrev);
3491
3492 /* No 0 delta motion events */
3493 litest_assert(x != 0.0 || y != 0.0 ||
3494 ux != 0.0 || uy != 0.0);
3495
3496 return ptrev;
3497 }
3498
3499 void
litest_assert_key_event(struct libinput * li,unsigned int key,enum libinput_key_state state)3500 litest_assert_key_event(struct libinput *li, unsigned int key,
3501 enum libinput_key_state state)
3502 {
3503 struct libinput_event *event;
3504
3505 litest_wait_for_event(li);
3506 event = libinput_get_event(li);
3507
3508 litest_is_keyboard_event(event, key, state);
3509
3510 libinput_event_destroy(event);
3511 }
3512
3513 void
litest_assert_button_event(struct libinput * li,unsigned int button,enum libinput_button_state state)3514 litest_assert_button_event(struct libinput *li, unsigned int button,
3515 enum libinput_button_state state)
3516 {
3517 struct libinput_event *event;
3518
3519 litest_wait_for_event(li);
3520 event = libinput_get_event(li);
3521
3522 litest_is_button_event(event, button, state);
3523
3524 libinput_event_destroy(event);
3525 }
3526
3527 struct libinput_event_touch *
litest_is_touch_event(struct libinput_event * event,enum libinput_event_type type)3528 litest_is_touch_event(struct libinput_event *event,
3529 enum libinput_event_type type)
3530 {
3531 struct libinput_event_touch *touch;
3532
3533 litest_assert_ptr_notnull(event);
3534
3535 if (type == 0)
3536 type = libinput_event_get_type(event);
3537
3538 switch (type) {
3539 case LIBINPUT_EVENT_TOUCH_DOWN:
3540 case LIBINPUT_EVENT_TOUCH_UP:
3541 case LIBINPUT_EVENT_TOUCH_MOTION:
3542 case LIBINPUT_EVENT_TOUCH_FRAME:
3543 case LIBINPUT_EVENT_TOUCH_CANCEL:
3544 litest_assert_event_type(event, type);
3545 break;
3546 default:
3547 ck_abort_msg("%s: invalid touch type %d\n", __func__, type);
3548 }
3549
3550 touch = libinput_event_get_touch_event(event);
3551
3552 return touch;
3553 }
3554
3555 struct libinput_event_keyboard *
litest_is_keyboard_event(struct libinput_event * event,unsigned int key,enum libinput_key_state state)3556 litest_is_keyboard_event(struct libinput_event *event,
3557 unsigned int key,
3558 enum libinput_key_state state)
3559 {
3560 struct libinput_event_keyboard *kevent;
3561 enum libinput_event_type type = LIBINPUT_EVENT_KEYBOARD_KEY;
3562
3563 litest_assert_ptr_notnull(event);
3564 litest_assert_event_type(event, type);
3565
3566 kevent = libinput_event_get_keyboard_event(event);
3567 litest_assert_ptr_notnull(kevent);
3568
3569 litest_assert_int_eq(libinput_event_keyboard_get_key(kevent), key);
3570 litest_assert_int_eq(libinput_event_keyboard_get_key_state(kevent),
3571 state);
3572 return kevent;
3573 }
3574
3575 struct libinput_event_gesture *
litest_is_gesture_event(struct libinput_event * event,enum libinput_event_type type,int nfingers)3576 litest_is_gesture_event(struct libinput_event *event,
3577 enum libinput_event_type type,
3578 int nfingers)
3579 {
3580 struct libinput_event_gesture *gevent;
3581
3582 litest_assert_ptr_notnull(event);
3583 litest_assert_event_type(event, type);
3584
3585 gevent = libinput_event_get_gesture_event(event);
3586 litest_assert_ptr_notnull(gevent);
3587
3588 if (nfingers != -1)
3589 litest_assert_int_eq(libinput_event_gesture_get_finger_count(gevent),
3590 nfingers);
3591 return gevent;
3592 }
3593
3594 struct libinput_event_tablet_tool *
litest_is_tablet_event(struct libinput_event * event,enum libinput_event_type type)3595 litest_is_tablet_event(struct libinput_event *event,
3596 enum libinput_event_type type)
3597 {
3598 struct libinput_event_tablet_tool *tevent;
3599
3600 litest_assert_ptr_notnull(event);
3601 litest_assert_event_type(event, type);
3602
3603 tevent = libinput_event_get_tablet_tool_event(event);
3604 litest_assert_ptr_notnull(tevent);
3605
3606 return tevent;
3607 }
3608
3609 void
litest_assert_tablet_button_event(struct libinput * li,unsigned int button,enum libinput_button_state state)3610 litest_assert_tablet_button_event(struct libinput *li, unsigned int button,
3611 enum libinput_button_state state)
3612 {
3613 struct libinput_event *event;
3614 struct libinput_event_tablet_tool *tev;
3615 enum libinput_event_type type = LIBINPUT_EVENT_TABLET_TOOL_BUTTON;
3616
3617 litest_wait_for_event(li);
3618 event = libinput_get_event(li);
3619
3620 litest_assert_notnull(event);
3621 litest_assert_event_type(event, type);
3622 tev = libinput_event_get_tablet_tool_event(event);
3623 litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev),
3624 button);
3625 litest_assert_int_eq(libinput_event_tablet_tool_get_button_state(tev),
3626 state);
3627 libinput_event_destroy(event);
3628 }
3629
3630
3631 struct libinput_event_tablet_tool *
litest_is_proximity_event(struct libinput_event * event,enum libinput_tablet_tool_proximity_state state)3632 litest_is_proximity_event(struct libinput_event *event,
3633 enum libinput_tablet_tool_proximity_state state)
3634 {
3635 struct libinput_event_tablet_tool *tev;
3636 enum libinput_event_type type = LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY;
3637
3638 litest_assert_notnull(event);
3639 litest_assert_event_type(event, type);
3640 tev = libinput_event_get_tablet_tool_event(event);
3641 litest_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tev),
3642 state);
3643 return tev;
3644 }
3645
litest_assert_tablet_proximity_event(struct libinput * li,enum libinput_tablet_tool_proximity_state state)3646 void litest_assert_tablet_proximity_event(struct libinput *li,
3647 enum libinput_tablet_tool_proximity_state state)
3648 {
3649 struct libinput_event *event;
3650
3651 litest_wait_for_event(li);
3652 event = libinput_get_event(li);
3653 litest_is_proximity_event(event, state);
3654 libinput_event_destroy(event);
3655 }
3656
litest_assert_tablet_tip_event(struct libinput * li,enum libinput_tablet_tool_tip_state state)3657 void litest_assert_tablet_tip_event(struct libinput *li,
3658 enum libinput_tablet_tool_tip_state state)
3659 {
3660 struct libinput_event *event;
3661 struct libinput_event_tablet_tool *tev;
3662 enum libinput_event_type type = LIBINPUT_EVENT_TABLET_TOOL_TIP;
3663
3664 litest_wait_for_event(li);
3665 event = libinput_get_event(li);
3666
3667 litest_assert_notnull(event);
3668 litest_assert_event_type(event, type);
3669 tev = libinput_event_get_tablet_tool_event(event);
3670 litest_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tev),
3671 state);
3672 libinput_event_destroy(event);
3673 }
3674
3675 struct libinput_event_tablet_pad *
litest_is_pad_button_event(struct libinput_event * event,unsigned int button,enum libinput_button_state state)3676 litest_is_pad_button_event(struct libinput_event *event,
3677 unsigned int button,
3678 enum libinput_button_state state)
3679 {
3680 struct libinput_event_tablet_pad *p;
3681 enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_BUTTON;
3682
3683 litest_assert_ptr_notnull(event);
3684 litest_assert_event_type(event, type);
3685
3686 p = libinput_event_get_tablet_pad_event(event);
3687 litest_assert_ptr_notnull(p);
3688
3689 litest_assert_int_eq(libinput_event_tablet_pad_get_button_number(p),
3690 button);
3691 litest_assert_int_eq(libinput_event_tablet_pad_get_button_state(p),
3692 state);
3693
3694 return p;
3695 }
3696
3697 struct libinput_event_tablet_pad *
litest_is_pad_ring_event(struct libinput_event * event,unsigned int number,enum libinput_tablet_pad_ring_axis_source source)3698 litest_is_pad_ring_event(struct libinput_event *event,
3699 unsigned int number,
3700 enum libinput_tablet_pad_ring_axis_source source)
3701 {
3702 struct libinput_event_tablet_pad *p;
3703 enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_RING;
3704
3705 litest_assert_ptr_notnull(event);
3706 litest_assert_event_type(event, type);
3707 p = libinput_event_get_tablet_pad_event(event);
3708
3709 litest_assert_int_eq(libinput_event_tablet_pad_get_ring_number(p),
3710 number);
3711 litest_assert_int_eq(libinput_event_tablet_pad_get_ring_source(p),
3712 source);
3713
3714 return p;
3715 }
3716
3717 struct libinput_event_tablet_pad *
litest_is_pad_strip_event(struct libinput_event * event,unsigned int number,enum libinput_tablet_pad_strip_axis_source source)3718 litest_is_pad_strip_event(struct libinput_event *event,
3719 unsigned int number,
3720 enum libinput_tablet_pad_strip_axis_source source)
3721 {
3722 struct libinput_event_tablet_pad *p;
3723 enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_STRIP;
3724
3725 litest_assert_ptr_notnull(event);
3726 litest_assert_event_type(event, type);
3727 p = libinput_event_get_tablet_pad_event(event);
3728
3729 litest_assert_int_eq(libinput_event_tablet_pad_get_strip_number(p),
3730 number);
3731 litest_assert_int_eq(libinput_event_tablet_pad_get_strip_source(p),
3732 source);
3733
3734 return p;
3735 }
3736
3737 struct libinput_event_tablet_pad *
litest_is_pad_key_event(struct libinput_event * event,unsigned int key,enum libinput_key_state state)3738 litest_is_pad_key_event(struct libinput_event *event,
3739 unsigned int key,
3740 enum libinput_key_state state)
3741 {
3742 struct libinput_event_tablet_pad *p;
3743 enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_KEY;
3744
3745 litest_assert(event != NULL);
3746 litest_assert_event_type(event, type);
3747
3748 p = libinput_event_get_tablet_pad_event(event);
3749 litest_assert(p != NULL);
3750
3751 litest_assert_int_eq(libinput_event_tablet_pad_get_key(p), key);
3752 litest_assert_int_eq(libinput_event_tablet_pad_get_key_state(p),
3753 state);
3754
3755 return p;
3756 }
3757
3758 struct libinput_event_switch *
litest_is_switch_event(struct libinput_event * event,enum libinput_switch sw,enum libinput_switch_state state)3759 litest_is_switch_event(struct libinput_event *event,
3760 enum libinput_switch sw,
3761 enum libinput_switch_state state)
3762 {
3763 struct libinput_event_switch *swev;
3764 enum libinput_event_type type = LIBINPUT_EVENT_SWITCH_TOGGLE;
3765
3766 litest_assert_notnull(event);
3767 litest_assert_event_type(event, type);
3768 swev = libinput_event_get_switch_event(event);
3769
3770 litest_assert_int_eq(libinput_event_switch_get_switch(swev), sw);
3771 litest_assert_int_eq(libinput_event_switch_get_switch_state(swev),
3772 state);
3773
3774 return swev;
3775 }
3776
3777 void
litest_assert_pad_button_event(struct libinput * li,unsigned int button,enum libinput_button_state state)3778 litest_assert_pad_button_event(struct libinput *li,
3779 unsigned int button,
3780 enum libinput_button_state state)
3781 {
3782 struct libinput_event *event;
3783 struct libinput_event_tablet_pad *pev;
3784
3785 litest_wait_for_event(li);
3786 event = libinput_get_event(li);
3787
3788 pev = litest_is_pad_button_event(event, button, state);
3789 libinput_event_destroy(libinput_event_tablet_pad_get_base_event(pev));
3790 }
3791
3792 void
litest_assert_pad_key_event(struct libinput * li,unsigned int key,enum libinput_key_state state)3793 litest_assert_pad_key_event(struct libinput *li,
3794 unsigned int key,
3795 enum libinput_key_state state)
3796 {
3797 struct libinput_event *event;
3798 struct libinput_event_tablet_pad *pev;
3799
3800 litest_wait_for_event(li);
3801 event = libinput_get_event(li);
3802
3803 pev = litest_is_pad_key_event(event, key, state);
3804 libinput_event_destroy(libinput_event_tablet_pad_get_base_event(pev));
3805 }
3806
3807 void
litest_assert_scroll(struct libinput * li,enum libinput_pointer_axis axis,int minimum_movement)3808 litest_assert_scroll(struct libinput *li,
3809 enum libinput_pointer_axis axis,
3810 int minimum_movement)
3811 {
3812 struct libinput_event *event, *next_event;
3813 struct libinput_event_pointer *ptrev;
3814 int value;
3815 int nevents = 0;
3816
3817 event = libinput_get_event(li);
3818 next_event = libinput_get_event(li);
3819 litest_assert_ptr_notnull(next_event); /* At least 1 scroll + stop scroll */
3820
3821 while (event) {
3822 ptrev = litest_is_axis_event(event, axis, 0);
3823 nevents++;
3824
3825 if (next_event) {
3826 int min = minimum_movement;
3827
3828 value = libinput_event_pointer_get_axis_value(ptrev,
3829 axis);
3830 /* Due to how the hysteresis works on touchpad
3831 * events, the first event is reduced by the
3832 * hysteresis margin that can cause the first event
3833 * go under the minimum we expect for all other
3834 * events */
3835 if (nevents == 1)
3836 min = minimum_movement/2;
3837
3838 /* Normal scroll event, check dir */
3839 if (minimum_movement > 0)
3840 litest_assert_int_ge(value, min);
3841 else
3842 litest_assert_int_le(value, min);
3843 } else {
3844 /* Last scroll event, must be 0 */
3845 ck_assert_double_eq(
3846 libinput_event_pointer_get_axis_value(ptrev, axis),
3847 0.0);
3848 }
3849 libinput_event_destroy(event);
3850 event = next_event;
3851 next_event = libinput_get_event(li);
3852 }
3853 }
3854
3855 void
litest_assert_only_typed_events(struct libinput * li,enum libinput_event_type type)3856 litest_assert_only_typed_events(struct libinput *li,
3857 enum libinput_event_type type)
3858 {
3859 struct libinput_event *event;
3860
3861 litest_assert(type != LIBINPUT_EVENT_NONE);
3862
3863 libinput_dispatch(li);
3864 event = libinput_get_event(li);
3865 litest_assert_notnull(event);
3866
3867 while (event) {
3868 litest_assert_int_eq(libinput_event_get_type(event),
3869 type);
3870 libinput_event_destroy(event);
3871 libinput_dispatch(li);
3872 event = libinput_get_event(li);
3873 }
3874 }
3875
3876 void
litest_assert_no_typed_events(struct libinput * li,enum libinput_event_type type)3877 litest_assert_no_typed_events(struct libinput *li,
3878 enum libinput_event_type type)
3879 {
3880 struct libinput_event *event;
3881
3882 litest_assert(type != LIBINPUT_EVENT_NONE);
3883
3884 libinput_dispatch(li);
3885 event = libinput_get_event(li);
3886
3887 while (event) {
3888 litest_assert_int_ne(libinput_event_get_type(event),
3889 type);
3890 libinput_event_destroy(event);
3891 libinput_dispatch(li);
3892 event = libinput_get_event(li);
3893 }
3894 }
3895
3896 void
litest_assert_touch_sequence(struct libinput * li)3897 litest_assert_touch_sequence(struct libinput *li)
3898 {
3899 struct libinput_event *event;
3900 struct libinput_event_touch *tev;
3901 int slot;
3902
3903 event = libinput_get_event(li);
3904 tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN);
3905 slot = libinput_event_touch_get_slot(tev);
3906 libinput_event_destroy(event);
3907
3908 event = libinput_get_event(li);
3909 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3910 libinput_event_destroy(event);
3911
3912 event = libinput_get_event(li);
3913 do {
3914 tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_MOTION);
3915 litest_assert_int_eq(slot, libinput_event_touch_get_slot(tev));
3916 libinput_event_destroy(event);
3917
3918 event = libinput_get_event(li);
3919 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3920 libinput_event_destroy(event);
3921
3922 event = libinput_get_event(li);
3923 litest_assert_notnull(event);
3924 } while (libinput_event_get_type(event) != LIBINPUT_EVENT_TOUCH_UP);
3925
3926 tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_UP);
3927 litest_assert_int_eq(slot, libinput_event_touch_get_slot(tev));
3928 libinput_event_destroy(event);
3929 event = libinput_get_event(li);
3930 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3931 libinput_event_destroy(event);
3932 }
3933
3934 void
litest_assert_touch_motion_frame(struct libinput * li)3935 litest_assert_touch_motion_frame(struct libinput *li)
3936 {
3937 struct libinput_event *event;
3938
3939 /* expect at least one, but maybe more */
3940 event = libinput_get_event(li);
3941 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_MOTION);
3942 libinput_event_destroy(event);
3943
3944 event = libinput_get_event(li);
3945 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3946 libinput_event_destroy(event);
3947
3948 event = libinput_get_event(li);
3949 while (event) {
3950 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_MOTION);
3951 libinput_event_destroy(event);
3952
3953 event = libinput_get_event(li);
3954 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3955 libinput_event_destroy(event);
3956
3957 event = libinput_get_event(li);
3958 }
3959 }
3960
3961 void
litest_assert_touch_down_frame(struct libinput * li)3962 litest_assert_touch_down_frame(struct libinput *li)
3963 {
3964 struct libinput_event *event;
3965
3966 event = libinput_get_event(li);
3967 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN);
3968 libinput_event_destroy(event);
3969
3970 event = libinput_get_event(li);
3971 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3972 libinput_event_destroy(event);
3973 }
3974
3975 void
litest_assert_touch_up_frame(struct libinput * li)3976 litest_assert_touch_up_frame(struct libinput *li)
3977 {
3978 struct libinput_event *event;
3979
3980 event = libinput_get_event(li);
3981 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_UP);
3982 libinput_event_destroy(event);
3983
3984 event = libinput_get_event(li);
3985 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3986 libinput_event_destroy(event);
3987 }
3988
3989 void
litest_assert_touch_cancel(struct libinput * li)3990 litest_assert_touch_cancel(struct libinput *li)
3991 {
3992 struct libinput_event *event;
3993
3994 event = libinput_get_event(li);
3995 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_CANCEL);
3996 libinput_event_destroy(event);
3997
3998 event = libinput_get_event(li);
3999 litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
4000 libinput_event_destroy(event);
4001 }
4002
4003 void
litest_timeout_tap(void)4004 litest_timeout_tap(void)
4005 {
4006 msleep(200);
4007 }
4008
4009 void
litest_timeout_tapndrag(void)4010 litest_timeout_tapndrag(void)
4011 {
4012 msleep(520);
4013 }
4014
4015 void
litest_timeout_debounce(void)4016 litest_timeout_debounce(void)
4017 {
4018 msleep(30);
4019 }
4020
4021 void
litest_timeout_softbuttons(void)4022 litest_timeout_softbuttons(void)
4023 {
4024 msleep(300);
4025 }
4026
4027 void
litest_timeout_buttonscroll(void)4028 litest_timeout_buttonscroll(void)
4029 {
4030 msleep(300);
4031 }
4032
4033 void
litest_timeout_finger_switch(void)4034 litest_timeout_finger_switch(void)
4035 {
4036 msleep(120);
4037 }
4038
4039 void
litest_timeout_edgescroll(void)4040 litest_timeout_edgescroll(void)
4041 {
4042 msleep(300);
4043 }
4044
4045 void
litest_timeout_middlebutton(void)4046 litest_timeout_middlebutton(void)
4047 {
4048 msleep(70);
4049 }
4050
4051 void
litest_timeout_dwt_short(void)4052 litest_timeout_dwt_short(void)
4053 {
4054 msleep(220);
4055 }
4056
4057 void
litest_timeout_dwt_long(void)4058 litest_timeout_dwt_long(void)
4059 {
4060 msleep(520);
4061 }
4062
4063 void
litest_timeout_gesture(void)4064 litest_timeout_gesture(void)
4065 {
4066 msleep(120);
4067 }
4068
4069 void
litest_timeout_gesture_scroll(void)4070 litest_timeout_gesture_scroll(void)
4071 {
4072 msleep(180);
4073 }
4074
4075 void
litest_timeout_trackpoint(void)4076 litest_timeout_trackpoint(void)
4077 {
4078 msleep(320);
4079 }
4080
4081 void
litest_timeout_tablet_proxout(void)4082 litest_timeout_tablet_proxout(void)
4083 {
4084 msleep(170);
4085 }
4086
4087 void
litest_timeout_touch_arbitration(void)4088 litest_timeout_touch_arbitration(void)
4089 {
4090 msleep(100);
4091 }
4092
4093 void
litest_timeout_hysteresis(void)4094 litest_timeout_hysteresis(void)
4095 {
4096 msleep(90);
4097 }
4098
4099 void
litest_push_event_frame(struct litest_device * dev)4100 litest_push_event_frame(struct litest_device *dev)
4101 {
4102 litest_assert_int_ge(dev->skip_ev_syn, 0);
4103 dev->skip_ev_syn++;
4104 }
4105
4106 void
litest_pop_event_frame(struct litest_device * dev)4107 litest_pop_event_frame(struct litest_device *dev)
4108 {
4109 litest_assert_int_gt(dev->skip_ev_syn, 0);
4110 dev->skip_ev_syn--;
4111 if (dev->skip_ev_syn == 0)
4112 litest_event(dev, EV_SYN, SYN_REPORT, 0);
4113 }
4114
4115 void
litest_filter_event(struct litest_device * dev,unsigned int type,unsigned int code)4116 litest_filter_event(struct litest_device *dev,
4117 unsigned int type,
4118 unsigned int code)
4119 {
4120 libevdev_disable_event_code(dev->evdev, type, code);
4121 }
4122
4123 void
litest_unfilter_event(struct litest_device * dev,unsigned int type,unsigned int code)4124 litest_unfilter_event(struct litest_device *dev,
4125 unsigned int type,
4126 unsigned int code)
4127 {
4128 /* would need an non-NULL argument for re-enabling, so simply abort
4129 * until we need to be more sophisticated */
4130 litest_assert_int_ne(type, (unsigned int)EV_ABS);
4131
4132 libevdev_enable_event_code(dev->evdev, type, code, NULL);
4133 }
4134
4135 static void
send_abs_xy(struct litest_device * d,double x,double y)4136 send_abs_xy(struct litest_device *d, double x, double y)
4137 {
4138 struct input_event e;
4139 int val;
4140
4141 e.type = EV_ABS;
4142 e.code = ABS_X;
4143 e.value = LITEST_AUTO_ASSIGN;
4144 val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true);
4145 litest_event(d, EV_ABS, ABS_X, val);
4146
4147 e.code = ABS_Y;
4148 val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true);
4149 litest_event(d, EV_ABS, ABS_Y, val);
4150 }
4151
4152 static void
send_abs_mt_xy(struct litest_device * d,double x,double y)4153 send_abs_mt_xy(struct litest_device *d, double x, double y)
4154 {
4155 struct input_event e;
4156 int val;
4157
4158 e.type = EV_ABS;
4159 e.code = ABS_MT_POSITION_X;
4160 e.value = LITEST_AUTO_ASSIGN;
4161 val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true);
4162 litest_event(d, EV_ABS, ABS_MT_POSITION_X, val);
4163
4164 e.code = ABS_MT_POSITION_Y;
4165 e.value = LITEST_AUTO_ASSIGN;
4166 val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true);
4167 litest_event(d, EV_ABS, ABS_MT_POSITION_Y, val);
4168 }
4169
4170 void
litest_semi_mt_touch_down(struct litest_device * d,struct litest_semi_mt * semi_mt,unsigned int slot,double x,double y)4171 litest_semi_mt_touch_down(struct litest_device *d,
4172 struct litest_semi_mt *semi_mt,
4173 unsigned int slot,
4174 double x, double y)
4175 {
4176 double t, l, r = 0, b = 0; /* top, left, right, bottom */
4177
4178 if (d->ntouches_down > 2 || slot > 1)
4179 return;
4180
4181 if (d->ntouches_down == 1) {
4182 l = x;
4183 t = y;
4184 } else {
4185 int other = (slot + 1) % 2;
4186 l = min(x, semi_mt->touches[other].x);
4187 t = min(y, semi_mt->touches[other].y);
4188 r = max(x, semi_mt->touches[other].x);
4189 b = max(y, semi_mt->touches[other].y);
4190 }
4191
4192 send_abs_xy(d, l, t);
4193
4194 litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
4195
4196 if (d->ntouches_down == 1)
4197 litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, ++semi_mt->tracking_id);
4198
4199 send_abs_mt_xy(d, l, t);
4200
4201 if (d->ntouches_down == 2) {
4202 litest_event(d, EV_ABS, ABS_MT_SLOT, 1);
4203 litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, ++semi_mt->tracking_id);
4204
4205 send_abs_mt_xy(d, r, b);
4206 }
4207
4208 litest_event(d, EV_SYN, SYN_REPORT, 0);
4209
4210 semi_mt->touches[slot].x = x;
4211 semi_mt->touches[slot].y = y;
4212 }
4213
4214 void
litest_semi_mt_touch_move(struct litest_device * d,struct litest_semi_mt * semi_mt,unsigned int slot,double x,double y)4215 litest_semi_mt_touch_move(struct litest_device *d,
4216 struct litest_semi_mt *semi_mt,
4217 unsigned int slot,
4218 double x, double y)
4219 {
4220 double t, l, r = 0, b = 0; /* top, left, right, bottom */
4221
4222 if (d->ntouches_down > 2 || slot > 1)
4223 return;
4224
4225 if (d->ntouches_down == 1) {
4226 l = x;
4227 t = y;
4228 } else {
4229 int other = (slot + 1) % 2;
4230 l = min(x, semi_mt->touches[other].x);
4231 t = min(y, semi_mt->touches[other].y);
4232 r = max(x, semi_mt->touches[other].x);
4233 b = max(y, semi_mt->touches[other].y);
4234 }
4235
4236 send_abs_xy(d, l, t);
4237
4238 litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
4239 send_abs_mt_xy(d, l, t);
4240
4241 if (d->ntouches_down == 2) {
4242 litest_event(d, EV_ABS, ABS_MT_SLOT, 1);
4243 send_abs_mt_xy(d, r, b);
4244 }
4245
4246 litest_event(d, EV_SYN, SYN_REPORT, 0);
4247
4248 semi_mt->touches[slot].x = x;
4249 semi_mt->touches[slot].y = y;
4250 }
4251
4252 void
litest_semi_mt_touch_up(struct litest_device * d,struct litest_semi_mt * semi_mt,unsigned int slot)4253 litest_semi_mt_touch_up(struct litest_device *d,
4254 struct litest_semi_mt *semi_mt,
4255 unsigned int slot)
4256 {
4257 /* note: ntouches_down is decreased before we get here */
4258 if (d->ntouches_down >= 2 || slot > 1)
4259 return;
4260
4261 litest_event(d, EV_ABS, ABS_MT_SLOT, d->ntouches_down);
4262 litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, -1);
4263
4264 /* if we have one finger left, send x/y coords for that finger left.
4265 this is likely to happen with a real touchpad */
4266 if (d->ntouches_down == 1) {
4267 int other = (slot + 1) % 2;
4268 send_abs_xy(d, semi_mt->touches[other].x, semi_mt->touches[other].y);
4269 litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
4270 send_abs_mt_xy(d, semi_mt->touches[other].x, semi_mt->touches[other].y);
4271 }
4272
4273 litest_event(d, EV_SYN, SYN_REPORT, 0);
4274 }
4275
4276 enum litest_mode {
4277 LITEST_MODE_ERROR,
4278 LITEST_MODE_TEST,
4279 LITEST_MODE_LIST,
4280 };
4281
4282 static inline enum litest_mode
litest_parse_argv(int argc,char ** argv)4283 litest_parse_argv(int argc, char **argv)
4284 {
4285 enum {
4286 OPT_FILTER_TEST,
4287 OPT_FILTER_DEVICE,
4288 OPT_FILTER_GROUP,
4289 OPT_FILTER_DEVICELESS,
4290 OPT_XML_PREFIX,
4291 OPT_JOBS,
4292 OPT_LIST,
4293 OPT_VERBOSE,
4294 };
4295 static const struct option opts[] = {
4296 { "filter-test", 1, 0, OPT_FILTER_TEST },
4297 { "filter-device", 1, 0, OPT_FILTER_DEVICE },
4298 { "filter-group", 1, 0, OPT_FILTER_GROUP },
4299 { "filter-deviceless", 0, 0, OPT_FILTER_DEVICELESS },
4300 { "xml-output", 1, 0, OPT_XML_PREFIX },
4301 { "jobs", 1, 0, OPT_JOBS },
4302 { "list", 0, 0, OPT_LIST },
4303 { "verbose", 0, 0, OPT_VERBOSE },
4304 { "help", 0, 0, 'h'},
4305 { 0, 0, 0, 0}
4306 };
4307 enum {
4308 JOBS_DEFAULT,
4309 JOBS_SINGLE,
4310 JOBS_CUSTOM
4311 } want_jobs = JOBS_DEFAULT;
4312 char *builddir;
4313 char *jobs_env;
4314
4315 /* If we are not running from the builddir, we assume we're running
4316 * against the system as installed */
4317 builddir = builddir_lookup();
4318 if (!builddir)
4319 use_system_rules_quirks = true;
4320 free(builddir);
4321
4322 if (in_debugger)
4323 want_jobs = JOBS_SINGLE;
4324
4325 if ((jobs_env = getenv("LITEST_JOBS"))) {
4326 if (!safe_atoi(jobs_env, &jobs)) {
4327 fprintf(stderr, "LITEST_JOBS environment variable must be positive integer\n");
4328 exit(EXIT_FAILURE);
4329 }
4330 }
4331
4332 while(1) {
4333 int c;
4334 int option_index = 0;
4335
4336 c = getopt_long(argc, argv, "j:", opts, &option_index);
4337 if (c == -1)
4338 break;
4339 switch(c) {
4340 default:
4341 case 'h':
4342 printf("Usage: %s [--verbose] [--jobs] [--filter-...]\n"
4343 "\n"
4344 "Options:\n"
4345 " --filter-test=.... \n"
4346 " Glob to filter on test names\n"
4347 " --filter-device=.... \n"
4348 " Glob to filter on device names\n"
4349 " --filter-group=.... \n"
4350 " Glob to filter on test groups\n"
4351 " --filter-deviceless=.... \n"
4352 " Glob to filter on tests that do not create test devices\n"
4353 " --xml-output=/path/to/file-XXXXXXX.xml\n"
4354 " Write test output in libcheck's XML format\n"
4355 " to the given files. The file must match the format\n"
4356 " prefix-XXXXXX.xml and only the prefix is your choice.\n"
4357 " --verbose\n"
4358 " Enable verbose output\n"
4359 " --jobs 8\n"
4360 " Number of parallel test suites to run (default: 8).\n"
4361 " This overrides the LITEST_JOBS environment variable.\n"
4362 " --list\n"
4363 " List all tests\n"
4364 "\n"
4365 "See the libinput-test-suite(1) man page for details.\n",
4366 program_invocation_short_name);
4367 exit(c != 'h');
4368 break;
4369 case OPT_FILTER_TEST:
4370 filter_test = optarg;
4371 if (want_jobs == JOBS_DEFAULT)
4372 want_jobs = JOBS_SINGLE;
4373 break;
4374 case OPT_FILTER_DEVICE:
4375 filter_device = optarg;
4376 if (want_jobs == JOBS_DEFAULT)
4377 want_jobs = JOBS_SINGLE;
4378 break;
4379 case OPT_FILTER_GROUP:
4380 filter_group = optarg;
4381 break;
4382 case OPT_XML_PREFIX:
4383 xml_prefix = optarg;
4384 break;
4385 case 'j':
4386 case OPT_JOBS:
4387 jobs = atoi(optarg);
4388 want_jobs = JOBS_CUSTOM;
4389 break;
4390 case OPT_LIST:
4391 return LITEST_MODE_LIST;
4392 case OPT_VERBOSE:
4393 verbose = true;
4394 break;
4395 case OPT_FILTER_DEVICELESS:
4396 run_deviceless = true;
4397 break;
4398 }
4399 }
4400
4401 if (want_jobs == JOBS_SINGLE)
4402 jobs = 1;
4403
4404 return LITEST_MODE_TEST;
4405 }
4406
4407 #ifndef LITEST_NO_MAIN
4408 static bool
is_debugger_attached(void)4409 is_debugger_attached(void)
4410 {
4411 int status;
4412 bool rc;
4413 int pid = fork();
4414
4415 if (pid == -1)
4416 return 0;
4417
4418 if (pid == 0) {
4419 int ppid = getppid();
4420 if (ptrace(PTRACE_ATTACH, ppid, NULL, 0) == 0) {
4421 waitpid(ppid, NULL, 0);
4422 ptrace(PTRACE_CONT, ppid, NULL, 0);
4423 ptrace(PTRACE_DETACH, ppid, NULL, 0);
4424 rc = false;
4425 } else {
4426 rc = true;
4427 }
4428 _exit(rc);
4429 } else {
4430 waitpid(pid, &status, 0);
4431 rc = WEXITSTATUS(status);
4432 }
4433
4434 return !!rc;
4435 }
4436
4437 static void
litest_list_tests(struct list * tests)4438 litest_list_tests(struct list *tests)
4439 {
4440 struct suite *s;
4441 const char *last_test_name = NULL;
4442
4443 list_for_each(s, tests, node) {
4444 struct test *t;
4445 printf("%s:\n", s->name);
4446 list_for_each(t, &s->tests, node) {
4447 if (!last_test_name ||
4448 !streq(last_test_name, t->name))
4449 printf(" %s:\n", t->name);
4450
4451 last_test_name = t->name;
4452
4453 printf(" %s\n", t->devname);
4454 }
4455 }
4456 }
4457
4458 extern const struct test_device __start_test_section, __stop_test_section;
4459
4460 static void
litest_init_test_devices(void)4461 litest_init_test_devices(void)
4462 {
4463 const struct test_device *t;
4464
4465 list_init(&devices);
4466
4467 for (t = &__start_test_section; t < &__stop_test_section; t++)
4468 list_append(&devices, &t->device->node);
4469 }
4470
4471 extern const struct test_collection __start_test_collection_section,
4472 __stop_test_collection_section;
4473
4474 static void
setup_tests(void)4475 setup_tests(void)
4476 {
4477 const struct test_collection *c;
4478
4479 for (c = &__start_test_collection_section;
4480 c < &__stop_test_collection_section;
4481 c++) {
4482 c->setup();
4483 }
4484 }
4485
4486 static int
check_device_access(void)4487 check_device_access(void)
4488 {
4489 if (getuid() != 0) {
4490 fprintf(stderr,
4491 "%s must be run as root.\n",
4492 program_invocation_short_name);
4493 return 77;
4494 }
4495
4496 if (access("/dev/uinput", F_OK) == -1 &&
4497 access("/dev/input/uinput", F_OK) == -1) {
4498 fprintf(stderr,
4499 "uinput device is missing, skipping tests.\n");
4500 return 77;
4501 }
4502
4503 return 0;
4504 }
4505
4506 static int
disable_tty(void)4507 disable_tty(void)
4508 {
4509 int tty_mode = -1;
4510
4511 /* If we're running 'normally' on the VT, disable the keyboard to
4512 * avoid messing up our host. But if we're inside gdb or running
4513 * without forking, leave it as-is.
4514 */
4515 if (!run_deviceless &&
4516 jobs > 1 &&
4517 !in_debugger &&
4518 getenv("CK_FORK") == NULL &&
4519 isatty(STDIN_FILENO) &&
4520 ioctl(STDIN_FILENO, KDGKBMODE, &tty_mode) == 0) {
4521 #ifdef __linux__
4522 ioctl(STDIN_FILENO, KDSKBMODE, K_OFF);
4523 #elif __FreeBSD__
4524 ioctl(STDIN_FILENO, KDSKBMODE, K_RAW);
4525
4526 /* Put the tty into raw mode */
4527 struct termios tios;
4528 if (tcgetattr(STDIN_FILENO, &tios))
4529 fprintf(stderr, "Failed to get terminal attribute: %d - %s\n", errno, strerror(errno));
4530 cfmakeraw(&tios);
4531 if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios))
4532 fprintf(stderr, "Failed to set terminal attribute: %d - %s\n", errno, strerror(errno));
4533 #endif
4534 }
4535
4536 return tty_mode;
4537 }
4538
4539 int
main(int argc,char ** argv)4540 main(int argc, char **argv)
4541 {
4542 const struct rlimit corelimit = { 0, 0 };
4543 enum litest_mode mode;
4544 int tty_mode = -1;
4545 int failed_tests;
4546 int rc;
4547
4548 in_debugger = is_debugger_attached();
4549 if (in_debugger || RUNNING_ON_VALGRIND)
4550 setenv("CK_FORK", "no", 0);
4551
4552 jobs = get_nprocs();
4553 if (!RUNNING_ON_VALGRIND)
4554 jobs *= 2;
4555
4556 mode = litest_parse_argv(argc, argv);
4557 if (mode == LITEST_MODE_ERROR)
4558 return EXIT_FAILURE;
4559
4560 if (!run_deviceless && (rc = check_device_access()) != 0)
4561 return rc;
4562
4563 litest_init_test_devices();
4564
4565 list_init(&all_tests);
4566
4567 setenv("CK_DEFAULT_TIMEOUT", "30", 0);
4568 setenv("LIBINPUT_RUNNING_TEST_SUITE", "1", 1);
4569
4570 setup_tests();
4571
4572 if (mode == LITEST_MODE_LIST) {
4573 litest_list_tests(&all_tests);
4574 return EXIT_SUCCESS;
4575 }
4576
4577 if (setrlimit(RLIMIT_CORE, &corelimit) != 0)
4578 perror("WARNING: Core dumps not disabled");
4579
4580 tty_mode = disable_tty();
4581
4582 failed_tests = litest_run(argc, argv);
4583
4584 if (tty_mode != -1) {
4585 ioctl(STDIN_FILENO, KDSKBMODE, tty_mode);
4586 #ifdef __FreeBSD__
4587 /* Put the tty into "sane" mode */
4588 struct termios tios;
4589 if (tcgetattr(STDIN_FILENO, &tios))
4590 fprintf(stderr, "Failed to get terminal attribute: %d - %s\n", errno, strerror(errno));
4591 cfmakesane(&tios);
4592 if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios))
4593 fprintf(stderr, "Failed to set terminal attribute: %d - %s\n", errno, strerror(errno));
4594 #endif
4595 }
4596
4597 return min(failed_tests, 255);
4598 }
4599 #endif
4600