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