test: add litest_assert_empty_queue helper function
[platform/upstream/libinput.git] / test / litest.c
1 /*
2  * Copyright © 2013 Red Hat, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #if HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <check.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <getopt.h>
31 #include <poll.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include "linux/input.h"
38 #include <sys/ptrace.h>
39 #include <sys/timerfd.h>
40 #include <sys/wait.h>
41
42 #include "litest.h"
43 #include "litest-int.h"
44 #include "libinput-util.h"
45
46 static int in_debugger = -1;
47
48 struct test {
49         struct list node;
50         char *name;
51         TCase *tc;
52         enum litest_device_type devices;
53 };
54
55 struct suite {
56         struct list node;
57         struct list tests;
58         char *name;
59         Suite *suite;
60 };
61
62 static struct litest_device *current_device;
63
64 struct litest_device *litest_current_device(void) {
65         return current_device;
66 }
67
68 void litest_set_current_device(struct litest_device *device) {
69         current_device = device;
70 }
71
72 void litest_generic_device_teardown(void)
73 {
74         litest_delete_device(current_device);
75         current_device = NULL;
76 }
77
78 extern struct litest_test_device litest_keyboard_device;
79 extern struct litest_test_device litest_synaptics_clickpad_device;
80 extern struct litest_test_device litest_synaptics_touchpad_device;
81 extern struct litest_test_device litest_trackpoint_device;
82 extern struct litest_test_device litest_bcm5974_device;
83 extern struct litest_test_device litest_mouse_device;
84 extern struct litest_test_device litest_wacom_touch_device;
85
86 struct litest_test_device* devices[] = {
87         &litest_synaptics_clickpad_device,
88         &litest_synaptics_touchpad_device,
89         &litest_keyboard_device,
90         &litest_trackpoint_device,
91         &litest_bcm5974_device,
92         &litest_mouse_device,
93         &litest_wacom_touch_device,
94         NULL,
95 };
96
97
98 static struct list all_tests;
99
100 static void
101 litest_add_tcase_for_device(struct suite *suite,
102                             void *func,
103                             const struct litest_test_device *dev)
104 {
105         struct test *t;
106         const char *test_name = dev->shortname;
107
108         list_for_each(t, &suite->tests, node) {
109                 if (strcmp(t->name, test_name) != 0)
110                         continue;
111
112                 tcase_add_test(t->tc, func);
113                 return;
114         }
115
116         t = zalloc(sizeof(*t));
117         t->name = strdup(test_name);
118         t->tc = tcase_create(test_name);
119         list_insert(&suite->tests, &t->node);
120         tcase_add_checked_fixture(t->tc, dev->setup,
121                                   dev->teardown ? dev->teardown : litest_generic_device_teardown);
122         tcase_add_test(t->tc, func);
123         suite_add_tcase(suite->suite, t->tc);
124 }
125
126 static void
127 litest_add_tcase_no_device(struct suite *suite, void *func)
128 {
129         struct test *t;
130         const char *test_name = "no device";
131
132         list_for_each(t, &suite->tests, node) {
133                 if (strcmp(t->name, test_name) != 0)
134                         continue;
135
136                 tcase_add_test(t->tc, func);
137                 return;
138         }
139
140         t = zalloc(sizeof(*t));
141         t->name = strdup(test_name);
142         t->tc = tcase_create(test_name);
143         list_insert(&suite->tests, &t->node);
144         tcase_add_test(t->tc, func);
145         suite_add_tcase(suite->suite, t->tc);
146 }
147
148 static void
149 litest_add_tcase(struct suite *suite, void *func,
150                  enum litest_device_feature required,
151                  enum litest_device_feature excluded)
152 {
153         struct litest_test_device **dev = devices;
154
155         if (required == LITEST_DISABLE_DEVICE &&
156             excluded == LITEST_DISABLE_DEVICE) {
157                 litest_add_tcase_no_device(suite, func);
158         } else if (required != LITEST_ANY || excluded != LITEST_ANY) {
159                 while (*dev) {
160                         if (((*dev)->features & required) == required &&
161                             ((*dev)->features & excluded) == 0)
162                                 litest_add_tcase_for_device(suite, func, *dev);
163                         dev++;
164                 }
165         } else {
166                 while (*dev) {
167                         litest_add_tcase_for_device(suite, func, *dev);
168                         dev++;
169                 }
170         }
171 }
172
173 void
174 litest_add_no_device(const char *name, void *func)
175 {
176         litest_add(name, func, LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE);
177 }
178
179 void
180 litest_add(const char *name,
181            void *func,
182            enum litest_device_feature required,
183            enum litest_device_feature excluded)
184 {
185         struct suite *s;
186
187         if (all_tests.next == NULL && all_tests.prev == NULL)
188                 list_init(&all_tests);
189
190         list_for_each(s, &all_tests, node) {
191                 if (strcmp(s->name, name) == 0) {
192                         litest_add_tcase(s, func, required, excluded);
193                         return;
194                 }
195         }
196
197         s = zalloc(sizeof(*s));
198         s->name = strdup(name);
199         s->suite = suite_create(s->name);
200
201         list_init(&s->tests);
202         list_insert(&all_tests, &s->node);
203         litest_add_tcase(s, func, required, excluded);
204 }
205
206 static int
207 is_debugger_attached(void)
208 {
209         int status;
210         int rc;
211         int pid = fork();
212
213         if (pid == -1)
214                 return 0;
215
216         if (pid == 0) {
217                 int ppid = getppid();
218                 if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) == 0) {
219                         waitpid(ppid, NULL, 0);
220                         ptrace(PTRACE_CONT, NULL, NULL);
221                         ptrace(PTRACE_DETACH, ppid, NULL, NULL);
222                         rc = 0;
223                 } else {
224                         rc = 1;
225                 }
226                 _exit(rc);
227         } else {
228                 waitpid(pid, &status, 0);
229                 rc = WEXITSTATUS(status);
230         }
231
232         return rc;
233 }
234
235
236 static void
237 litest_list_tests(struct list *tests)
238 {
239         struct suite *s;
240
241         list_for_each(s, tests, node) {
242                 struct test *t;
243                 printf("%s:\n", s->name);
244                 list_for_each(t, &s->tests, node) {
245                         printf("        %s\n", t->name);
246                 }
247         }
248 }
249
250 static void
251 litest_log_handler(enum libinput_log_priority pri,
252                    void *user_data,
253                    const char *format,
254                    va_list args)
255 {
256         const char *priority = NULL;
257
258         switch(pri) {
259         case LIBINPUT_LOG_PRIORITY_INFO: priority = "info"; break;
260         case LIBINPUT_LOG_PRIORITY_ERROR: priority = "error"; break;
261         case LIBINPUT_LOG_PRIORITY_DEBUG: priority = "debug"; break;
262         }
263
264         fprintf(stderr, "litest %s: ", priority);
265         vfprintf(stderr, format, args);
266 }
267
268 static const struct option opts[] = {
269         { "list", 0, 0, 'l' },
270         { "verbose", 0, 0, 'v' },
271         { 0, 0, 0, 0}
272 };
273
274 int
275 litest_run(int argc, char **argv) {
276         struct suite *s, *snext;
277         int failed;
278         SRunner *sr = NULL;
279
280         if (in_debugger == -1) {
281                 in_debugger = is_debugger_attached();
282                 if (in_debugger)
283                         setenv("CK_FORK", "no", 0);
284         }
285
286         list_for_each(s, &all_tests, node) {
287                 if (!sr)
288                         sr = srunner_create(s->suite);
289                 else
290                         srunner_add_suite(sr, s->suite);
291         }
292
293         while(1) {
294                 int c;
295                 int option_index = 0;
296
297                 c = getopt_long(argc, argv, "", opts, &option_index);
298                 if (c == -1)
299                         break;
300                 switch(c) {
301                         case 'l':
302                                 litest_list_tests(&all_tests);
303                                 return 0;
304                         case 'v':
305                                 libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_DEBUG);
306                                 libinput_log_set_handler(litest_log_handler, NULL);
307                                 break;
308                         default:
309                                 fprintf(stderr, "usage: %s [--list]\n", argv[0]);
310                                 return 1;
311
312                 }
313         }
314
315         srunner_run_all(sr, CK_NORMAL);
316         failed = srunner_ntests_failed(sr);
317         srunner_free(sr);
318
319         list_for_each_safe(s, snext, &all_tests, node) {
320                 struct test *t, *tnext;
321
322                 list_for_each_safe(t, tnext, &s->tests, node) {
323                         free(t->name);
324                         list_remove(&t->node);
325                         free(t);
326                 }
327
328                 list_remove(&s->node);
329                 free(s->name);
330                 free(s);
331         }
332
333         return failed;
334 }
335
336 static int
337 open_restricted(const char *path, int flags, void *userdata)
338 {
339         return open(path, flags);
340 }
341
342 static void
343 close_restricted(int fd, void *userdata)
344 {
345         close(fd);
346 }
347
348 const struct libinput_interface interface = {
349         .open_restricted = open_restricted,
350         .close_restricted = close_restricted,
351 };
352
353
354 static struct input_absinfo *
355 merge_absinfo(const struct input_absinfo *orig,
356               const struct input_absinfo *override)
357 {
358         struct input_absinfo *abs;
359         int nelem, i;
360         size_t sz = ABS_MAX + 1;
361
362         if (!orig)
363                 return NULL;
364
365         abs = calloc(sz, sizeof(*abs));
366         ck_assert(abs != NULL);
367
368         nelem = 0;
369         while (orig[nelem].value != -1) {
370                 abs[nelem] = orig[nelem];
371                 nelem++;
372                 ck_assert_int_lt(nelem, sz);
373         }
374
375         /* just append, if the same axis is present twice, libevdev will
376            only use the last value anyway */
377         i = 0;
378         while (override && override[i].value != -1) {
379                 abs[nelem++] = override[i++];
380                 ck_assert_int_lt(nelem, sz);
381         }
382
383         ck_assert_int_lt(nelem, sz);
384         abs[nelem].value = -1;
385
386         return abs;
387 }
388
389 static int*
390 merge_events(const int *orig, const int *override)
391 {
392         int *events;
393         int nelem, i;
394         size_t sz = KEY_MAX * 3;
395
396         if (!orig)
397                 return NULL;
398
399         events = calloc(sz, sizeof(int));
400         ck_assert(events != NULL);
401
402         nelem = 0;
403         while (orig[nelem] != -1) {
404                 events[nelem] = orig[nelem];
405                 nelem++;
406                 ck_assert_int_lt(nelem, sz);
407         }
408
409         /* just append, if the same axis is present twice, libevdev will
410          * ignore the double definition anyway */
411         i = 0;
412         while (override && override[i] != -1) {
413                 events[nelem++] = override[i++];
414                 ck_assert_int_le(nelem, sz);
415         }
416
417         ck_assert_int_lt(nelem, sz);
418         events[nelem] = -1;
419
420         return events;
421 }
422
423
424 static struct litest_device *
425 litest_create(enum litest_device_type which,
426               const char *name_override,
427               struct input_id *id_override,
428               const struct input_absinfo *abs_override,
429               const int *events_override)
430 {
431         struct litest_device *d = NULL;
432         struct litest_test_device **dev;
433         const char *name;
434         const struct input_id *id;
435         struct input_absinfo *abs;
436         int *events;
437
438         dev = devices;
439         while (*dev) {
440                 if ((*dev)->type == which)
441                         break;
442                 dev++;
443         }
444
445         if (!*dev)
446                 ck_abort_msg("Invalid device type %d\n", which);
447
448         d = zalloc(sizeof(*d));
449         ck_assert(d != NULL);
450
451         /* device has custom create method */
452         if ((*dev)->create) {
453                 (*dev)->create(d);
454                 if (abs_override || events_override)
455                         ck_abort_msg("Custom create cannot"
456                                      "be overridden");
457
458                 return d;
459         }
460
461         abs = merge_absinfo((*dev)->absinfo, abs_override);
462         events = merge_events((*dev)->events, events_override);
463         name = name_override ? name_override : (*dev)->name;
464         id = id_override ? id_override : (*dev)->id;
465
466         d->uinput = litest_create_uinput_device_from_description(name,
467                                                                  id,
468                                                                  abs,
469                                                                  events);
470         d->interface = (*dev)->interface;
471         free(abs);
472         free(events);
473
474         return d;
475
476 }
477
478 struct libinput *
479 litest_create_context(void)
480 {
481         struct libinput *libinput =
482                 libinput_path_create_context(&interface, NULL);
483         ck_assert_notnull(libinput);
484         return libinput;
485 }
486
487 struct litest_device *
488 litest_add_device_with_overrides(struct libinput *libinput,
489                                  enum litest_device_type which,
490                                  const char *name_override,
491                                  struct input_id *id_override,
492                                  const struct input_absinfo *abs_override,
493                                  const int *events_override)
494 {
495         struct litest_device *d;
496         int fd;
497         int rc;
498         const char *path;
499
500         d = litest_create(which,
501                           name_override,
502                           id_override,
503                           abs_override,
504                           events_override);
505
506         path = libevdev_uinput_get_devnode(d->uinput);
507         ck_assert(path != NULL);
508         fd = open(path, O_RDWR|O_NONBLOCK);
509         ck_assert_int_ne(fd, -1);
510
511         rc = libevdev_new_from_fd(fd, &d->evdev);
512         ck_assert_int_eq(rc, 0);
513
514         d->libinput = libinput;
515         d->libinput_device = libinput_path_add_device(d->libinput, path);
516         ck_assert(d->libinput_device != NULL);
517         libinput_device_ref(d->libinput_device);
518
519         if (d->interface) {
520                 d->interface->min[ABS_X] = libevdev_get_abs_minimum(d->evdev, ABS_X);
521                 d->interface->max[ABS_X] = libevdev_get_abs_maximum(d->evdev, ABS_X);
522                 d->interface->min[ABS_Y] = libevdev_get_abs_minimum(d->evdev, ABS_Y);
523                 d->interface->max[ABS_Y] = libevdev_get_abs_maximum(d->evdev, ABS_Y);
524         }
525         return d;
526 }
527
528 struct litest_device *
529 litest_create_device_with_overrides(enum litest_device_type which,
530                                     const char *name_override,
531                                     struct input_id *id_override,
532                                     const struct input_absinfo *abs_override,
533                                     const int *events_override)
534 {
535         struct litest_device *dev =
536                 litest_add_device_with_overrides(litest_create_context(),
537                                                  which,
538                                                  name_override,
539                                                  id_override,
540                                                  abs_override,
541                                                  events_override);
542         dev->owns_context = true;
543         return dev;
544 }
545
546 struct litest_device *
547 litest_create_device(enum litest_device_type which)
548 {
549         return litest_create_device_with_overrides(which, NULL, NULL, NULL, NULL);
550 }
551
552 int
553 litest_handle_events(struct litest_device *d)
554 {
555         struct pollfd fd;
556
557         fd.fd = libinput_get_fd(d->libinput);
558         fd.events = POLLIN;
559
560         while (poll(&fd, 1, 1))
561                 libinput_dispatch(d->libinput);
562
563         return 0;
564 }
565
566 void
567 litest_delete_device(struct litest_device *d)
568 {
569         if (!d)
570                 return;
571
572         libinput_device_unref(d->libinput_device);
573         if (d->owns_context)
574                 libinput_destroy(d->libinput);
575         libevdev_free(d->evdev);
576         libevdev_uinput_destroy(d->uinput);
577         memset(d,0, sizeof(*d));
578         free(d);
579 }
580
581 void
582 litest_event(struct litest_device *d, unsigned int type,
583              unsigned int code, int value)
584 {
585         libevdev_uinput_write_event(d->uinput, type, code, value);
586 }
587
588 static int
589 auto_assign_value(struct litest_device *d,
590                   const struct input_event *ev,
591                   int slot, int x, int y)
592 {
593         static int tracking_id;
594         int value = ev->value;
595
596         if (value != LITEST_AUTO_ASSIGN || ev->type != EV_ABS)
597                 return value;
598
599         switch (ev->code) {
600         case ABS_X:
601         case ABS_MT_POSITION_X:
602                 value = litest_scale(d, ABS_X, x);
603                 break;
604         case ABS_Y:
605         case ABS_MT_POSITION_Y:
606                 value = litest_scale(d, ABS_Y, y);
607                 break;
608         case ABS_MT_TRACKING_ID:
609                 value = ++tracking_id;
610                 break;
611         case ABS_MT_SLOT:
612                 value = slot;
613                 break;
614         }
615
616         return value;
617 }
618
619
620 void
621 litest_touch_down(struct litest_device *d, unsigned int slot, int x, int y)
622 {
623         struct input_event *ev;
624
625         if (d->interface->touch_down) {
626                 d->interface->touch_down(d, slot, x, y);
627                 return;
628         }
629
630         ev = d->interface->touch_down_events;
631         while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
632                 int value = auto_assign_value(d, ev, slot, x, y);
633                 litest_event(d, ev->type, ev->code, value);
634                 ev++;
635         }
636 }
637
638 void
639 litest_touch_up(struct litest_device *d, unsigned int slot)
640 {
641         struct input_event *ev;
642         struct input_event up[] = {
643                 { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
644                 { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
645                 { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
646                 { .type = -1, .code = -1 }
647         };
648
649         if (d->interface->touch_up) {
650                 d->interface->touch_up(d, slot);
651                 return;
652         } else if (d->interface->touch_up_events) {
653                 ev = d->interface->touch_up_events;
654         } else
655                 ev = up;
656
657         while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
658                 int value = auto_assign_value(d, ev, slot, 0, 0);
659                 litest_event(d, ev->type, ev->code, value);
660                 ev++;
661         }
662 }
663
664 void
665 litest_touch_move(struct litest_device *d, unsigned int slot, int x, int y)
666 {
667         struct input_event *ev;
668
669         if (d->interface->touch_move) {
670                 d->interface->touch_move(d, slot, x, y);
671                 return;
672         }
673
674         ev = d->interface->touch_move_events;
675         while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
676                 int value = auto_assign_value(d, ev, slot, x, y);
677                 litest_event(d, ev->type, ev->code, value);
678                 ev++;
679         }
680 }
681
682 void
683 litest_touch_move_to(struct litest_device *d,
684                      unsigned int slot,
685                      int x_from, int y_from,
686                      int x_to, int y_to,
687                      int steps)
688 {
689         for (int i = 0; i < steps - 1; i++)
690                 litest_touch_move(d, slot,
691                                   x_from + (x_to - x_from)/steps * i,
692                                   y_from + (y_to - y_from)/steps * i);
693         litest_touch_move(d, slot, x_to, y_to);
694 }
695
696 void
697 litest_button_click(struct litest_device *d, unsigned int button, bool is_press)
698 {
699
700         struct input_event *ev;
701         struct input_event click[] = {
702                 { .type = EV_KEY, .code = button, .value = is_press ? 1 : 0 },
703                 { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
704         };
705
706         ARRAY_FOR_EACH(click, ev)
707                 litest_event(d, ev->type, ev->code, ev->value);
708 }
709
710 void
711 litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press)
712 {
713         litest_button_click(d, key, is_press);
714 }
715
716 int litest_scale(const struct litest_device *d, unsigned int axis, int val)
717 {
718         int min, max;
719         ck_assert_int_ge(val, 0);
720         ck_assert_int_le(val, 100);
721         ck_assert_int_le(axis, ABS_Y);
722
723         min = d->interface->min[axis];
724         max = d->interface->max[axis];
725         return (max - min) * val/100.0 + min;
726 }
727
728 void
729 litest_drain_events(struct libinput *li)
730 {
731         struct libinput_event *event;
732
733         libinput_dispatch(li);
734         while ((event = libinput_get_event(li))) {
735                 libinput_event_destroy(event);
736                 libinput_dispatch(li);
737         }
738 }
739
740 static void
741 litest_print_event(struct libinput_event *event)
742 {
743         struct libinput_event_pointer *p;
744         struct libinput_device *dev;
745         enum libinput_event_type type;
746         double x, y;
747
748         dev = libinput_event_get_device(event);
749         type = libinput_event_get_type(event);
750
751         fprintf(stderr,
752                 "device %s type %d ",
753                 libinput_device_get_sysname(dev),
754                 type);
755         switch (type) {
756         case LIBINPUT_EVENT_POINTER_MOTION:
757                 p = libinput_event_get_pointer_event(event);
758                 x = libinput_event_pointer_get_dx(p);
759                 y = libinput_event_pointer_get_dy(p);
760                 fprintf(stderr, "motion: %.2f/%.2f", x, y);
761                 break;
762         case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
763                 p = libinput_event_get_pointer_event(event);
764                 x = libinput_event_pointer_get_absolute_x(p);
765                 y = libinput_event_pointer_get_absolute_y(p);
766                 fprintf(stderr, "motion: %.2f/%.2f", x, y);
767                 break;
768         case LIBINPUT_EVENT_POINTER_BUTTON:
769                 p = libinput_event_get_pointer_event(event);
770                 fprintf(stderr,
771                         "button: %d state %d",
772                         libinput_event_pointer_get_button(p),
773                         libinput_event_pointer_get_button_state(p));
774                 break;
775         default:
776                 break;
777         }
778
779         fprintf(stderr, "\n");
780 }
781
782 void
783 litest_assert_empty_queue(struct libinput *li)
784 {
785         bool empty_queue = true;
786         struct libinput_event *event;
787
788         libinput_dispatch(li);
789         while ((event = libinput_get_event(li))) {
790                 empty_queue = false;
791                 fprintf(stderr,
792                         "Unexpected event: ");
793                 litest_print_event(event);
794                 libinput_event_destroy(event);
795                 libinput_dispatch(li);
796         }
797
798         ck_assert(empty_queue);
799 }
800
801 struct libevdev_uinput *
802 litest_create_uinput_device_from_description(const char *name,
803                                              const struct input_id *id,
804                                              const struct input_absinfo *abs,
805                                              const int *events)
806 {
807         struct libevdev_uinput *uinput;
808         struct libevdev *dev;
809         int type, code;
810         int rc;
811         const struct input_absinfo default_abs = {
812                 .value = 0,
813                 .minimum = 0,
814                 .maximum = 0xffff,
815                 .fuzz = 0,
816                 .flat = 0,
817                 .resolution = 100
818         };
819
820         dev = libevdev_new();
821         ck_assert(dev != NULL);
822
823         libevdev_set_name(dev, name);
824         if (id) {
825                 libevdev_set_id_bustype(dev, id->bustype);
826                 libevdev_set_id_vendor(dev, id->vendor);
827                 libevdev_set_id_product(dev, id->product);
828         }
829
830         while (abs && abs->value != -1) {
831                 rc = libevdev_enable_event_code(dev, EV_ABS,
832                                                 abs->value, abs);
833                 ck_assert_int_eq(rc, 0);
834                 abs++;
835         }
836
837         while (events &&
838                (type = *events++) != -1 &&
839                (code = *events++) != -1) {
840                 if (type == INPUT_PROP_MAX) {
841                         rc = libevdev_enable_property(dev, code);
842                 } else {
843                         if (type != EV_SYN)
844                                 ck_assert(!libevdev_has_event_code(dev, type, code));
845                         rc = libevdev_enable_event_code(dev, type, code,
846                                                         type == EV_ABS ? &default_abs : NULL);
847                 }
848                 ck_assert_int_eq(rc, 0);
849         }
850
851         rc = libevdev_uinput_create_from_device(dev,
852                                                 LIBEVDEV_UINPUT_OPEN_MANAGED,
853                                                 &uinput);
854         ck_assert_int_eq(rc, 0);
855
856         libevdev_free(dev);
857
858         return uinput;
859 }
860
861 static struct libevdev_uinput *
862 litest_create_uinput_abs_device_v(const char *name,
863                                   struct input_id *id,
864                                   const struct input_absinfo *abs,
865                                   va_list args)
866 {
867         int events[KEY_MAX * 2 + 2]; /* increase this if not sufficient */
868         int *event = events;
869         int type, code;
870
871         while ((type = va_arg(args, int)) != -1 &&
872                (code = va_arg(args, int)) != -1) {
873                 *event++ = type;
874                 *event++ = code;
875                 ck_assert(event < &events[ARRAY_LENGTH(events) - 2]);
876         }
877
878         *event++ = -1;
879         *event++ = -1;
880
881         return litest_create_uinput_device_from_description(name, id,
882                                                             abs, events);
883 }
884
885 struct libevdev_uinput *
886 litest_create_uinput_abs_device(const char *name,
887                                 struct input_id *id,
888                                 const struct input_absinfo *abs,
889                                 ...)
890 {
891         struct libevdev_uinput *uinput;
892         va_list args;
893
894         va_start(args, abs);
895         uinput = litest_create_uinput_abs_device_v(name, id, abs, args);
896         va_end(args);
897
898         return uinput;
899 }
900
901 struct libevdev_uinput *
902 litest_create_uinput_device(const char *name, struct input_id *id, ...)
903 {
904         struct libevdev_uinput *uinput;
905         va_list args;
906
907         va_start(args, id);
908         uinput = litest_create_uinput_abs_device_v(name, id, NULL, args);
909         va_end(args);
910
911         return uinput;
912 }