tests: Add FreeBSD specific tests
[platform/upstream/libevdev.git] / test / test-uinput.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 #include "config.h"
24 #include <linux/input.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <fcntl.h>
29 #include <libevdev/libevdev-uinput.h>
30
31 #include "test-common.h"
32 #define UINPUT_NODE "/dev/uinput"
33
34 START_TEST(test_uinput_create_device)
35 {
36         struct libevdev *dev, *dev2;
37         struct libevdev_uinput *uidev;
38         int fd, uinput_fd;
39         unsigned int type, code;
40         int rc;
41         const char *devnode;
42
43         dev = libevdev_new();
44         ck_assert(dev != NULL);
45         libevdev_set_name(dev, TEST_DEVICE_NAME);
46         libevdev_enable_event_type(dev, EV_SYN);
47         libevdev_enable_event_type(dev, EV_REL);
48         libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
49         libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
50         libevdev_enable_event_code(dev, EV_REL, REL_MAX, NULL);
51
52         rc = libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev);
53         ck_assert_int_eq(rc, 0);
54         ck_assert(uidev != NULL);
55
56         uinput_fd = libevdev_uinput_get_fd(uidev);
57         ck_assert_int_gt(uinput_fd, -1);
58
59         devnode = libevdev_uinput_get_devnode(uidev);
60         ck_assert(devnode != NULL);
61
62         fd = open(devnode, O_RDONLY);
63         ck_assert_int_gt(fd, -1);
64         rc = libevdev_new_from_fd(fd, &dev2);
65         ck_assert_int_eq(rc, 0);
66
67         for (type = 0; type < EV_CNT; type++) {
68                 int max = libevdev_event_type_get_max(type);
69                 if (max == -1)
70                         continue;
71
72                 for (code = 0; code < (unsigned int)max; code++) {
73                         ck_assert_int_eq(libevdev_has_event_code(dev, type, code),
74                                          libevdev_has_event_code(dev2, type, code));
75                 }
76         }
77
78         libevdev_free(dev);
79         libevdev_free(dev2);
80         libevdev_uinput_destroy(uidev);
81         close(fd);
82
83         /* uinput fd is managed, so make sure it did get closed */
84         ck_assert_int_eq(close(uinput_fd), -1);
85         ck_assert_int_eq(errno, EBADF);
86
87 }
88 END_TEST
89
90 START_TEST(test_uinput_create_device_invalid)
91 {
92         struct libevdev *dev;
93         struct libevdev_uinput *uidev = NULL;
94         int rc;
95
96         dev = libevdev_new();
97         ck_assert(dev != NULL);
98         libevdev_set_name(dev, TEST_DEVICE_NAME);
99         libevdev_enable_event_type(dev, EV_SYN);
100         libevdev_enable_event_type(dev, EV_REL);
101         libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
102         libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
103
104         libevdev_set_log_function(test_logfunc_ignore_error, NULL);
105         rc = libevdev_uinput_create_from_device(dev, -1, &uidev);
106         ck_assert_int_eq(rc, -EBADF);
107         ck_assert(uidev == NULL);
108         libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
109
110         libevdev_free(dev);
111 }
112 END_TEST
113
114 START_TEST(test_uinput_create_device_from_fd)
115 {
116         struct libevdev *dev, *dev2;
117         struct libevdev_uinput *uidev;
118         int fd, fd2;
119         unsigned int type, code;
120         int rc;
121         const char *devnode;
122
123         dev = libevdev_new();
124         ck_assert(dev != NULL);
125         libevdev_set_name(dev, TEST_DEVICE_NAME);
126         libevdev_enable_event_type(dev, EV_SYN);
127         libevdev_enable_event_type(dev, EV_REL);
128         libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
129         libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
130
131         fd = open(UINPUT_NODE, O_RDWR);
132         ck_assert_int_gt(fd, -1);
133
134         rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
135         ck_assert_int_eq(rc, 0);
136         ck_assert(uidev != NULL);
137
138         ck_assert_int_eq(libevdev_uinput_get_fd(uidev), fd);
139
140         devnode = libevdev_uinput_get_devnode(uidev);
141         ck_assert(devnode != NULL);
142
143         fd2 = open(devnode, O_RDONLY);
144         ck_assert_int_gt(fd2, -1);
145         rc = libevdev_new_from_fd(fd2, &dev2);
146         ck_assert_int_eq(rc, 0);
147
148         for (type = 0; type < EV_CNT; type++) {
149                 int max = libevdev_event_type_get_max(type);
150                 if (max == -1)
151                         continue;
152
153                 for (code = 0; code < (unsigned int)max; code++) {
154                         ck_assert_int_eq(libevdev_has_event_code(dev, type, code),
155                                          libevdev_has_event_code(dev2, type, code));
156                 }
157         }
158
159         libevdev_free(dev);
160         libevdev_free(dev2);
161         libevdev_uinput_destroy(uidev);
162         close(fd);
163         close(fd2);
164 }
165 END_TEST
166
167 #ifdef __FreeBSD__
168 START_TEST(test_uinput_check_devnode_bsd)
169 {
170         struct libevdev *dev;
171         struct libevdev_uinput *uidev, *uidev2;
172         const char *devnode, *devnode2;
173         int fd, fd2;
174         int rc;
175
176         dev = libevdev_new();
177         ck_assert(dev != NULL);
178         libevdev_set_name(dev, TEST_DEVICE_NAME);
179         libevdev_enable_event_type(dev, EV_SYN);
180         libevdev_enable_event_type(dev, EV_REL);
181         libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
182         libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
183
184         fd = open(UINPUT_NODE, O_RDWR);
185         ck_assert_int_gt(fd, -1);
186         fd2 = open(UINPUT_NODE, O_RDWR);
187         ck_assert_int_gt(fd2, -1);
188
189         rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
190         ck_assert_int_eq(rc, 0);
191
192         /* create a second one */
193         libevdev_set_name(dev, TEST_DEVICE_NAME " 2");
194         rc = libevdev_uinput_create_from_device(dev, fd2, &uidev2);
195         ck_assert_int_eq(rc, 0);
196
197         devnode = libevdev_uinput_get_devnode(uidev);
198         ck_assert(devnode != NULL);
199
200         /* get syspath twice returns same pointer */
201         devnode2 = libevdev_uinput_get_devnode(uidev);
202         ck_assert(devnode == devnode2);
203
204         /* second dev has different devnode */
205         devnode2 = libevdev_uinput_get_devnode(uidev2);
206         ck_assert(strcmp(devnode, devnode2) != 0);
207
208         libevdev_uinput_destroy(uidev2);
209         libevdev_uinput_destroy(uidev);
210
211         close(fd2);
212         close(fd);
213
214         libevdev_free(dev);
215 }
216 END_TEST
217
218 START_TEST(test_uinput_check_syspath_bsd)
219 {
220         struct libevdev *dev;
221         struct libevdev_uinput *uidev;
222         const char *syspath;
223         int fd;
224         int rc;
225
226         dev = libevdev_new();
227         ck_assert(dev != NULL);
228         libevdev_set_name(dev, TEST_DEVICE_NAME);
229         libevdev_enable_event_type(dev, EV_SYN);
230         libevdev_enable_event_type(dev, EV_REL);
231         libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
232         libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
233
234         fd = open(UINPUT_NODE, O_RDWR);
235         ck_assert_int_gt(fd, -1);
236
237         rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
238         ck_assert_int_eq(rc, 0);
239
240         syspath = libevdev_uinput_get_syspath(uidev);
241         /* FreeBSD should always return NULL for libevdev_unput_get_syspath() */
242         ck_assert(syspath == NULL);
243
244         libevdev_uinput_destroy(uidev);
245
246         close(fd);
247
248         libevdev_free(dev);
249 }
250 END_TEST
251
252 #else /* !__FreeBSD__ */
253
254 START_TEST(test_uinput_check_syspath_time)
255 {
256         struct libevdev *dev;
257         struct libevdev_uinput *uidev, *uidev2;
258         const char *syspath, *syspath2;
259         int fd, fd2;
260         int rc;
261
262         dev = libevdev_new();
263         ck_assert(dev != NULL);
264         libevdev_set_name(dev, TEST_DEVICE_NAME);
265         libevdev_enable_event_type(dev, EV_SYN);
266         libevdev_enable_event_type(dev, EV_REL);
267         libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
268         libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
269
270         fd = open(UINPUT_NODE, O_RDWR);
271         ck_assert_int_gt(fd, -1);
272         fd2 = open(UINPUT_NODE, O_RDWR);
273         ck_assert_int_gt(fd2, -1);
274
275         rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
276         ck_assert_int_eq(rc, 0);
277
278         /* sleep for 1.5 seconds. sysfs resolution is 1 second, so
279            creating both devices without delay means
280            libevdev_uinput_get_syspath can't actually differ between
281            them. By waiting, we get different ctime for uidev and uidev2,
282            and exercise that part of the code.
283          */
284         usleep(1500000);
285
286         /* create a second one to test the syspath time filtering code */
287         rc = libevdev_uinput_create_from_device(dev, fd2, &uidev2);
288         ck_assert_int_eq(rc, 0);
289
290         syspath = libevdev_uinput_get_syspath(uidev);
291         ck_assert(syspath != NULL);
292
293         /* get syspath twice returns same pointer */
294         syspath2 = libevdev_uinput_get_syspath(uidev);
295         ck_assert(syspath == syspath2);
296
297         /* second dev has different syspath */
298         syspath2 = libevdev_uinput_get_syspath(uidev2);
299         ck_assert(strcmp(syspath, syspath2) != 0);
300
301         libevdev_free(dev);
302         libevdev_uinput_destroy(uidev);
303         libevdev_uinput_destroy(uidev2);
304
305         close(fd);
306         close(fd2);
307 }
308 END_TEST
309
310 START_TEST(test_uinput_check_syspath_name)
311 {
312         struct libevdev *dev;
313         struct libevdev_uinput *uidev, *uidev2;
314         const char *syspath, *syspath2;
315         int fd, fd2;
316         int rc;
317
318         dev = libevdev_new();
319         ck_assert(dev != NULL);
320         libevdev_set_name(dev, TEST_DEVICE_NAME);
321         libevdev_enable_event_type(dev, EV_SYN);
322         libevdev_enable_event_type(dev, EV_REL);
323         libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
324         libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
325
326         fd = open(UINPUT_NODE, O_RDWR);
327         ck_assert_int_gt(fd, -1);
328         fd2 = open(UINPUT_NODE, O_RDWR);
329         ck_assert_int_gt(fd2, -1);
330
331         rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
332         ck_assert_int_eq(rc, 0);
333
334         /* create a second one to stress the syspath filtering code */
335         libevdev_set_name(dev, TEST_DEVICE_NAME " 2");
336         rc = libevdev_uinput_create_from_device(dev, fd2, &uidev2);
337         ck_assert_int_eq(rc, 0);
338
339         syspath = libevdev_uinput_get_syspath(uidev);
340         ck_assert(syspath != NULL);
341
342         /* get syspath twice returns same pointer */
343         syspath2 = libevdev_uinput_get_syspath(uidev);
344         ck_assert(syspath == syspath2);
345
346         /* second dev has different syspath */
347         syspath2 = libevdev_uinput_get_syspath(uidev2);
348         ck_assert(strcmp(syspath, syspath2) != 0);
349
350         libevdev_free(dev);
351         libevdev_uinput_destroy(uidev);
352         libevdev_uinput_destroy(uidev2);
353
354         close(fd);
355         close(fd2);
356 }
357 END_TEST
358
359 #endif /* __FreeBSD __ */
360
361 START_TEST(test_uinput_events)
362 {
363         struct libevdev *dev;
364         struct libevdev_uinput *uidev;
365         int fd, fd2;
366         int rc;
367         const char *devnode;
368         int i;
369         const int nevents = 5;
370         struct input_event events[] = { {{0, 0}, EV_REL, REL_X, 1},
371                                         {{0, 0}, EV_REL, REL_Y, -1},
372                                         {{0, 0}, EV_SYN, SYN_REPORT, 0},
373                                         {{0, 0}, EV_KEY, BTN_LEFT, 1},
374                                         {{0, 0}, EV_SYN, SYN_REPORT, 0}};
375         struct input_event events_read[nevents];
376
377         dev = libevdev_new();
378         ck_assert(dev != NULL);
379         libevdev_set_name(dev, TEST_DEVICE_NAME);
380         libevdev_enable_event_type(dev, EV_SYN);
381         libevdev_enable_event_type(dev, EV_REL);
382         libevdev_enable_event_type(dev, EV_KEY);
383         libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
384         libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
385         libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT, NULL);
386
387         fd = open(UINPUT_NODE, O_RDWR);
388         ck_assert_int_gt(fd, -1);
389
390         rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
391         ck_assert_int_eq(rc, 0);
392         ck_assert(uidev != NULL);
393
394         devnode = libevdev_uinput_get_devnode(uidev);
395         ck_assert(devnode != NULL);
396
397         fd2 = open(devnode, O_RDONLY);
398
399         for (i = 0; i < nevents; i++)
400                 libevdev_uinput_write_event(uidev, events[i].type, events[i].code, events[i].value);
401
402         rc = read(fd2, events_read, sizeof(events_read));
403         ck_assert_int_eq(rc, sizeof(events_read));
404
405         for (i = 0; i < nevents; i++) {
406                 ck_assert_int_eq(events[i].type, events_read[i].type);
407                 ck_assert_int_eq(events[i].code, events_read[i].code);
408                 ck_assert_int_eq(events[i].value, events_read[i].value);
409         }
410
411         libevdev_free(dev);
412         libevdev_uinput_destroy(uidev);
413         close(fd);
414         close(fd2);
415 }
416 END_TEST
417
418 START_TEST(test_uinput_properties)
419 {
420         struct libevdev *dev, *dev2;
421         struct libevdev_uinput *uidev;
422         int fd;
423         int rc;
424         const char *devnode;
425
426         dev = libevdev_new();
427         ck_assert(dev != NULL);
428         libevdev_set_name(dev, TEST_DEVICE_NAME);
429         libevdev_enable_event_type(dev, EV_SYN);
430         libevdev_enable_event_type(dev, EV_REL);
431         libevdev_enable_event_type(dev, EV_KEY);
432         libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
433         libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
434         libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT, NULL);
435         libevdev_enable_property(dev, INPUT_PROP_BUTTONPAD);
436         libevdev_enable_property(dev, INPUT_PROP_MAX);
437
438         rc = libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev);
439         ck_assert_int_eq(rc, 0);
440         ck_assert(uidev != NULL);
441
442         devnode = libevdev_uinput_get_devnode(uidev);
443         ck_assert(devnode != NULL);
444
445         fd = open(devnode, O_RDONLY);
446         ck_assert_int_gt(fd, -1);
447         rc = libevdev_new_from_fd(fd, &dev2);
448         ck_assert_int_eq(rc, 0);
449
450         ck_assert(libevdev_has_property(dev2, INPUT_PROP_BUTTONPAD));
451         ck_assert(libevdev_has_property(dev2, INPUT_PROP_MAX));
452
453         libevdev_free(dev);
454         libevdev_free(dev2);
455         libevdev_uinput_destroy(uidev);
456         close(fd);
457 }
458 END_TEST
459
460 TEST_SUITE_ROOT_PRIVILEGES(uinput_suite)
461 {
462         Suite *s = suite_create("libevdev uinput device tests");
463
464         add_test(s, test_uinput_create_device);
465         add_test(s, test_uinput_create_device_invalid);
466         add_test(s, test_uinput_create_device_from_fd);
467 #ifdef __FreeBSD__
468         add_test(s, test_uinput_check_devnode_bsd);
469         add_test(s, test_uinput_check_syspath_bsd);
470 #else
471         add_test(s, test_uinput_check_syspath_time);
472         add_test(s, test_uinput_check_syspath_name);
473 #endif
474
475         add_test(s, test_uinput_events);
476
477         add_test(s, test_uinput_properties);
478
479         return s;
480 }