1 /*
2 * Copyright © 2018 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <config.h>
25
26 #include <check.h>
27 #include <libinput.h>
28
29 #include "libinput-util.h"
30 #include "litest.h"
31 #include "quirks.h"
32
33 static void
log_handler(struct libinput * this_is_null,enum libinput_log_priority priority,const char * format,va_list args)34 log_handler(struct libinput *this_is_null,
35 enum libinput_log_priority priority,
36 const char *format,
37 va_list args)
38 {
39 #if 0
40 vprintf(format, args);
41 #endif
42 }
43
44 struct data_dir {
45 char *dirname;
46 char *filename;
47 };
48
49 static struct data_dir
make_data_dir(const char * file_content)50 make_data_dir(const char *file_content)
51 {
52 struct data_dir dir = {0};
53 char dirname[PATH_MAX] = "/tmp/litest-quirk-test-XXXXXX";
54 char *filename;
55 FILE *fp;
56 int rc;
57
58 litest_assert_notnull(mkdtemp(dirname));
59 dir.dirname = safe_strdup(dirname);
60
61 if (file_content) {
62 rc = xasprintf(&filename, "%s/testfile.quirks", dirname);
63 litest_assert_int_eq(rc, (int)(strlen(dirname) + 16));
64
65 fp = fopen(filename, "w+");
66 litest_assert_notnull(fp);
67 rc = fputs(file_content, fp);
68 fclose(fp);
69 litest_assert_int_ge(rc, 0);
70 dir.filename = filename;
71 }
72
73 return dir;
74 }
75
76 static void
cleanup_data_dir(struct data_dir dd)77 cleanup_data_dir(struct data_dir dd)
78 {
79 if (dd.filename) {
80 unlink(dd.filename);
81 free(dd.filename);
82 }
83 if (dd.dirname) {
84 rmdir(dd.dirname);
85 free(dd.dirname);
86 }
87 }
88
START_TEST(quirks_invalid_dir)89 START_TEST(quirks_invalid_dir)
90 {
91 struct quirks_context *ctx;
92
93 ctx = quirks_init_subsystem("/does-not-exist",
94 NULL,
95 log_handler,
96 NULL,
97 QLOG_LIBINPUT_LOGGING);
98 ck_assert(ctx == NULL);
99 }
100 END_TEST
101
START_TEST(quirks_empty_dir)102 START_TEST(quirks_empty_dir)
103 {
104 struct quirks_context *ctx;
105 struct data_dir dd = make_data_dir(NULL);
106
107 ctx = quirks_init_subsystem(dd.dirname,
108 NULL,
109 log_handler,
110 NULL,
111 QLOG_LIBINPUT_LOGGING);
112 ck_assert(ctx == NULL);
113
114 cleanup_data_dir(dd);
115 }
116 END_TEST
117
START_TEST(quirks_section_empty)118 START_TEST(quirks_section_empty)
119 {
120 struct quirks_context *ctx;
121 const char quirks_file[] = "[Empty Section]";
122 struct data_dir dd = make_data_dir(quirks_file);
123
124 ctx = quirks_init_subsystem(dd.dirname,
125 NULL,
126 log_handler,
127 NULL,
128 QLOG_CUSTOM_LOG_PRIORITIES);
129 ck_assert(ctx == NULL);
130 cleanup_data_dir(dd);
131 }
132 END_TEST
133
START_TEST(quirks_section_double)134 START_TEST(quirks_section_double)
135 {
136 struct quirks_context *ctx;
137 const char quirks_file[] = "[Section name]";
138 struct data_dir dd = make_data_dir(quirks_file);
139
140 ctx = quirks_init_subsystem(dd.dirname,
141 NULL,
142 log_handler,
143 NULL,
144 QLOG_CUSTOM_LOG_PRIORITIES);
145 ck_assert(ctx == NULL);
146 cleanup_data_dir(dd);
147 }
148 END_TEST
149
START_TEST(quirks_section_missing_match)150 START_TEST(quirks_section_missing_match)
151 {
152 struct quirks_context *ctx;
153 const char quirks_file[] =
154 "[Section name]\n"
155 "AttrSizeHint=10x10\n";
156 struct data_dir dd = make_data_dir(quirks_file);
157
158 ctx = quirks_init_subsystem(dd.dirname,
159 NULL,
160 log_handler,
161 NULL,
162 QLOG_CUSTOM_LOG_PRIORITIES);
163 ck_assert(ctx == NULL);
164 cleanup_data_dir(dd);
165 }
166 END_TEST
167
START_TEST(quirks_section_missing_attr)168 START_TEST(quirks_section_missing_attr)
169 {
170 struct quirks_context *ctx;
171 const char quirks_file[] =
172 "[Section name]\n"
173 "MatchUdevType=mouse\n";
174 struct data_dir dd = make_data_dir(quirks_file);
175
176 ctx = quirks_init_subsystem(dd.dirname,
177 NULL,
178 log_handler,
179 NULL,
180 QLOG_CUSTOM_LOG_PRIORITIES);
181 ck_assert(ctx == NULL);
182 cleanup_data_dir(dd);
183 }
184 END_TEST
185
START_TEST(quirks_section_match_after_attr)186 START_TEST(quirks_section_match_after_attr)
187 {
188 struct quirks_context *ctx;
189 const char quirks_file[] =
190 "[Section name]\n"
191 "MatchUdevType=mouse\n"
192 "AttrSizeHint=10x10\n"
193 "MatchName=mouse\n";
194 struct data_dir dd = make_data_dir(quirks_file);
195
196 ctx = quirks_init_subsystem(dd.dirname,
197 NULL,
198 log_handler,
199 NULL,
200 QLOG_CUSTOM_LOG_PRIORITIES);
201 ck_assert(ctx == NULL);
202 cleanup_data_dir(dd);
203 }
204 END_TEST
205
START_TEST(quirks_section_duplicate_match)206 START_TEST(quirks_section_duplicate_match)
207 {
208 struct quirks_context *ctx;
209 const char quirks_file[] =
210 "[Section name]\n"
211 "MatchUdevType=mouse\n"
212 "MatchUdevType=mouse\n"
213 "AttrSizeHint=10x10\n";
214 struct data_dir dd = make_data_dir(quirks_file);
215
216 ctx = quirks_init_subsystem(dd.dirname,
217 NULL,
218 log_handler,
219 NULL,
220 QLOG_CUSTOM_LOG_PRIORITIES);
221 ck_assert(ctx == NULL);
222 cleanup_data_dir(dd);
223 }
224 END_TEST
225
START_TEST(quirks_section_duplicate_attr)226 START_TEST(quirks_section_duplicate_attr)
227 {
228 /* This shouldn't be allowed but the current parser
229 is happy with it */
230 struct quirks_context *ctx;
231 const char quirks_file[] =
232 "[Section name]\n"
233 "MatchUdevType=mouse\n"
234 "AttrSizeHint=10x10\n"
235 "AttrSizeHint=10x10\n";
236 struct data_dir dd = make_data_dir(quirks_file);
237
238 ctx = quirks_init_subsystem(dd.dirname,
239 NULL,
240 log_handler,
241 NULL,
242 QLOG_CUSTOM_LOG_PRIORITIES);
243 ck_assert_notnull(ctx);
244 quirks_context_unref(ctx);
245 cleanup_data_dir(dd);
246 }
247 END_TEST
248
START_TEST(quirks_parse_error_section)249 START_TEST(quirks_parse_error_section)
250 {
251 struct quirks_context *ctx;
252 const char quirks_file[] =
253 "[Section Missing Bracket\n"
254 "MatchUdevType=mouse\n"
255 "AttrSizeHint=10x10\n";
256 struct data_dir dd = make_data_dir(quirks_file);
257
258 ctx = quirks_init_subsystem(dd.dirname,
259 NULL,
260 log_handler,
261 NULL,
262 QLOG_CUSTOM_LOG_PRIORITIES);
263 ck_assert(ctx == NULL);
264 cleanup_data_dir(dd);
265 }
266 END_TEST
267
START_TEST(quirks_parse_error_trailing_whitespace)268 START_TEST(quirks_parse_error_trailing_whitespace)
269 {
270 struct quirks_context *ctx;
271 const char quirks_file[] =
272 "[Section name]\n"
273 "MatchUdevType=mouse \n"
274 "AttrSizeHint=10x10\n";
275 struct data_dir dd = make_data_dir(quirks_file);
276
277 ctx = quirks_init_subsystem(dd.dirname,
278 NULL,
279 log_handler,
280 NULL,
281 QLOG_CUSTOM_LOG_PRIORITIES);
282 ck_assert(ctx == NULL);
283 cleanup_data_dir(dd);
284 }
285 END_TEST
286
START_TEST(quirks_parse_error_unknown_match)287 START_TEST(quirks_parse_error_unknown_match)
288 {
289 struct quirks_context *ctx;
290 const char quirks_file[] =
291 "[Section name]\n"
292 "Matchblahblah=mouse\n"
293 "AttrSizeHint=10x10\n";
294 struct data_dir dd = make_data_dir(quirks_file);
295
296 ctx = quirks_init_subsystem(dd.dirname,
297 NULL,
298 log_handler,
299 NULL,
300 QLOG_CUSTOM_LOG_PRIORITIES);
301 ck_assert(ctx == NULL);
302 cleanup_data_dir(dd);
303 }
304 END_TEST
305
START_TEST(quirks_parse_error_unknown_attr)306 START_TEST(quirks_parse_error_unknown_attr)
307 {
308 struct quirks_context *ctx;
309 const char quirks_file[] =
310 "[Section name]\n"
311 "MatchUdevType=mouse\n"
312 "Attrblahblah=10x10\n";
313 struct data_dir dd = make_data_dir(quirks_file);
314
315 ctx = quirks_init_subsystem(dd.dirname,
316 NULL,
317 log_handler,
318 NULL,
319 QLOG_CUSTOM_LOG_PRIORITIES);
320 ck_assert(ctx == NULL);
321 cleanup_data_dir(dd);
322 }
323 END_TEST
324
START_TEST(quirks_parse_error_unknown_model)325 START_TEST(quirks_parse_error_unknown_model)
326 {
327 struct quirks_context *ctx;
328 const char quirks_file[] =
329 "[Section name]\n"
330 "MatchUdevType=mouse\n"
331 "Modelblahblah=1\n";
332 struct data_dir dd = make_data_dir(quirks_file);
333
334 ctx = quirks_init_subsystem(dd.dirname,
335 NULL,
336 log_handler,
337 NULL,
338 QLOG_CUSTOM_LOG_PRIORITIES);
339 ck_assert(ctx == NULL);
340 cleanup_data_dir(dd);
341 }
342 END_TEST
343
START_TEST(quirks_parse_error_unknown_prefix)344 START_TEST(quirks_parse_error_unknown_prefix)
345 {
346 struct quirks_context *ctx;
347 const char quirks_file[] =
348 "[Section name]\n"
349 "MatchUdevType=mouse\n"
350 "Fooblahblah=10x10\n";
351 struct data_dir dd = make_data_dir(quirks_file);
352
353 ctx = quirks_init_subsystem(dd.dirname,
354 NULL,
355 log_handler,
356 NULL,
357 QLOG_CUSTOM_LOG_PRIORITIES);
358 ck_assert(ctx == NULL);
359 cleanup_data_dir(dd);
360 }
361 END_TEST
362
START_TEST(quirks_parse_error_model_not_one)363 START_TEST(quirks_parse_error_model_not_one)
364 {
365 struct quirks_context *ctx;
366 const char quirks_file[] =
367 "[Section name]\n"
368 "MatchUdevType=mouse\n"
369 "ModelAppleTouchpad=true\n";
370 struct data_dir dd = make_data_dir(quirks_file);
371
372 ctx = quirks_init_subsystem(dd.dirname,
373 NULL,
374 log_handler,
375 NULL,
376 QLOG_CUSTOM_LOG_PRIORITIES);
377 ck_assert(ctx == NULL);
378 cleanup_data_dir(dd);
379 }
380 END_TEST
381
START_TEST(quirks_parse_comment_inline)382 START_TEST(quirks_parse_comment_inline)
383 {
384 struct quirks_context *ctx;
385 const char quirks_file[] =
386 "[Section name] # some inline comment\n"
387 "MatchUdevType=mouse\t # another inline comment\n"
388 "ModelAppleTouchpad=1#\n";
389 struct data_dir dd = make_data_dir(quirks_file);
390
391 ctx = quirks_init_subsystem(dd.dirname,
392 NULL,
393 log_handler,
394 NULL,
395 QLOG_CUSTOM_LOG_PRIORITIES);
396 ck_assert_notnull(ctx);
397 quirks_context_unref(ctx);
398 cleanup_data_dir(dd);
399 }
400 END_TEST
401
START_TEST(quirks_parse_comment_empty)402 START_TEST(quirks_parse_comment_empty)
403 {
404 struct quirks_context *ctx;
405 const char quirks_file[] =
406 "[Section name]\n"
407 "#\n"
408 " #\n"
409 "MatchUdevType=mouse\n"
410 "ModelAppleTouchpad=1\n";
411 struct data_dir dd = make_data_dir(quirks_file);
412
413 ctx = quirks_init_subsystem(dd.dirname,
414 NULL,
415 log_handler,
416 NULL,
417 QLOG_CUSTOM_LOG_PRIORITIES);
418 ck_assert_notnull(ctx);
419 quirks_context_unref(ctx);
420 cleanup_data_dir(dd);
421 }
422 END_TEST
423
START_TEST(quirks_parse_string_quotes_single)424 START_TEST(quirks_parse_string_quotes_single)
425 {
426 struct quirks_context *ctx;
427 const char quirks_file[] =
428 "[Section name]\n"
429 "MatchUdevType=mouse\n"
430 "AttrKeyboardIntegration='internal'\n";
431 struct data_dir dd = make_data_dir(quirks_file);
432
433 ctx = quirks_init_subsystem(dd.dirname,
434 NULL,
435 log_handler,
436 NULL,
437 QLOG_CUSTOM_LOG_PRIORITIES);
438 ck_assert(ctx == NULL);
439 quirks_context_unref(ctx);
440 cleanup_data_dir(dd);
441 }
442 END_TEST
443
START_TEST(quirks_parse_string_quotes_double)444 START_TEST(quirks_parse_string_quotes_double)
445 {
446 struct quirks_context *ctx;
447 const char quirks_file[] =
448 "[Section name]\n"
449 "MatchUdevType=mouse\n"
450 "AttrKeyboardIntegration=\"internal\"\n";
451 struct data_dir dd = make_data_dir(quirks_file);
452
453 ctx = quirks_init_subsystem(dd.dirname,
454 NULL,
455 log_handler,
456 NULL,
457 QLOG_CUSTOM_LOG_PRIORITIES);
458 ck_assert(ctx == NULL);
459 quirks_context_unref(ctx);
460 cleanup_data_dir(dd);
461 }
462 END_TEST
463
START_TEST(quirks_parse_bustype)464 START_TEST(quirks_parse_bustype)
465 {
466 struct quirks_context *ctx;
467 const char quirks_file[] =
468 "[Section name]\n"
469 "MatchBus=usb\n"
470 "ModelAppleTouchpad=1\n"
471 "\n"
472 "[Section name]\n"
473 "MatchBus=bluetooth\n"
474 "ModelAppleTouchpad=1\n"
475 "\n"
476 "[Section name]\n"
477 "MatchBus=i2c\n"
478 "ModelAppleTouchpad=1\n"
479 "\n"
480 "[Section name]\n"
481 "MatchBus=rmi\n"
482 "ModelAppleTouchpad=1\n"
483 "\n"
484 "[Section name]\n"
485 "MatchBus=ps2\n"
486 "ModelAppleTouchpad=1\n";
487 struct data_dir dd = make_data_dir(quirks_file);
488
489 ctx = quirks_init_subsystem(dd.dirname,
490 NULL,
491 log_handler,
492 NULL,
493 QLOG_CUSTOM_LOG_PRIORITIES);
494 ck_assert_notnull(ctx);
495 quirks_context_unref(ctx);
496 cleanup_data_dir(dd);
497 }
498 END_TEST
499
START_TEST(quirks_parse_bustype_invalid)500 START_TEST(quirks_parse_bustype_invalid)
501 {
502 struct quirks_context *ctx;
503 const char quirks_file[] =
504 "[Section name]\n"
505 "MatchBus=venga\n"
506 "ModelAppleTouchpad=1\n";
507 struct data_dir dd = make_data_dir(quirks_file);
508
509 ctx = quirks_init_subsystem(dd.dirname,
510 NULL,
511 log_handler,
512 NULL,
513 QLOG_CUSTOM_LOG_PRIORITIES);
514 ck_assert(ctx == NULL);
515 cleanup_data_dir(dd);
516 }
517 END_TEST
518
START_TEST(quirks_parse_vendor)519 START_TEST(quirks_parse_vendor)
520 {
521 struct quirks_context *ctx;
522 const char quirks_file[] =
523 "[Section name]\n"
524 "MatchVendor=0x0000\n"
525 "ModelAppleTouchpad=1\n"
526 "\n"
527 "[Section name]\n"
528 "MatchVendor=0x0001\n"
529 "ModelAppleTouchpad=1\n"
530 "\n"
531 "[Section name]\n"
532 "MatchVendor=0x2343\n"
533 "ModelAppleTouchpad=1\n";
534 struct data_dir dd = make_data_dir(quirks_file);
535
536 ctx = quirks_init_subsystem(dd.dirname,
537 NULL,
538 log_handler,
539 NULL,
540 QLOG_CUSTOM_LOG_PRIORITIES);
541 ck_assert_notnull(ctx);
542 quirks_context_unref(ctx);
543 cleanup_data_dir(dd);
544 }
545 END_TEST
546
START_TEST(quirks_parse_vendor_invalid)547 START_TEST(quirks_parse_vendor_invalid)
548 {
549 struct quirks_context *ctx;
550 const char *quirks_file[] = {
551 "[Section name]\n"
552 "MatchVendor=-1\n"
553 "ModelAppleTouchpad=1\n",
554 "[Section name]\n"
555 "MatchVendor=abc\n"
556 "ModelAppleTouchpad=1\n",
557 "[Section name]\n"
558 "MatchVendor=0xFFFFF\n"
559 "ModelAppleTouchpad=1\n",
560 "[Section name]\n"
561 "MatchVendor=123\n"
562 "ModelAppleTouchpad=1\n",
563 };
564 const char **qf;
565
566 ARRAY_FOR_EACH(quirks_file, qf) {
567 struct data_dir dd = make_data_dir(*qf);
568
569 ctx = quirks_init_subsystem(dd.dirname,
570 NULL,
571 log_handler,
572 NULL,
573 QLOG_CUSTOM_LOG_PRIORITIES);
574 ck_assert(ctx == NULL);
575 cleanup_data_dir(dd);
576 }
577 }
578 END_TEST
579
START_TEST(quirks_parse_product)580 START_TEST(quirks_parse_product)
581 {
582 struct quirks_context *ctx;
583 const char quirks_file[] =
584 "[Section name]\n"
585 "MatchProduct=0x0000\n"
586 "ModelAppleTouchpad=1\n"
587 "\n"
588 "[Section name]\n"
589 "MatchProduct=0x0001\n"
590 "ModelAppleTouchpad=1\n"
591 "\n"
592 "[Section name]\n"
593 "MatchProduct=0x2343\n"
594 "ModelAppleTouchpad=1\n";
595 struct data_dir dd = make_data_dir(quirks_file);
596
597 ctx = quirks_init_subsystem(dd.dirname,
598 NULL,
599 log_handler,
600 NULL,
601 QLOG_CUSTOM_LOG_PRIORITIES);
602 ck_assert_notnull(ctx);
603 quirks_context_unref(ctx);
604 cleanup_data_dir(dd);
605 }
606 END_TEST
607
START_TEST(quirks_parse_product_invalid)608 START_TEST(quirks_parse_product_invalid)
609 {
610 struct quirks_context *ctx;
611 const char *quirks_file[] = {
612 "[Section name]\n"
613 "MatchProduct=-1\n"
614 "ModelAppleTouchpad=1\n",
615 "[Section name]\n"
616 "MatchProduct=abc\n"
617 "ModelAppleTouchpad=1\n",
618 "[Section name]\n"
619 "MatchProduct=0xFFFFF\n"
620 "ModelAppleTouchpad=1\n",
621 "[Section name]\n"
622 "MatchProduct=123\n"
623 "ModelAppleTouchpad=1\n",
624 };
625 const char **qf;
626
627 ARRAY_FOR_EACH(quirks_file, qf) {
628 struct data_dir dd = make_data_dir(*qf);
629
630 ctx = quirks_init_subsystem(dd.dirname,
631 NULL,
632 log_handler,
633 NULL,
634 QLOG_CUSTOM_LOG_PRIORITIES);
635 ck_assert(ctx == NULL);
636 cleanup_data_dir(dd);
637 }
638 }
639 END_TEST
640
START_TEST(quirks_parse_version)641 START_TEST(quirks_parse_version)
642 {
643 struct quirks_context *ctx;
644 const char quirks_file[] =
645 "[Section name]\n"
646 "MatchVersion=0x0000\n"
647 "ModelAppleTouchpad=1\n"
648 "\n"
649 "[Section name]\n"
650 "MatchVersion=0x0001\n"
651 "ModelAppleTouchpad=1\n"
652 "\n"
653 "[Section name]\n"
654 "MatchVersion=0x2343\n"
655 "ModelAppleTouchpad=1\n";
656 struct data_dir dd = make_data_dir(quirks_file);
657
658 ctx = quirks_init_subsystem(dd.dirname,
659 NULL,
660 log_handler,
661 NULL,
662 QLOG_CUSTOM_LOG_PRIORITIES);
663 ck_assert_notnull(ctx);
664 quirks_context_unref(ctx);
665 cleanup_data_dir(dd);
666 }
667 END_TEST
668
START_TEST(quirks_parse_version_invalid)669 START_TEST(quirks_parse_version_invalid)
670 {
671 struct quirks_context *ctx;
672 const char *quirks_file[] = {
673 "[Section name]\n"
674 "MatchVersion=-1\n"
675 "ModelAppleTouchpad=1\n",
676 "[Section name]\n"
677 "MatchVersion=abc\n"
678 "ModelAppleTouchpad=1\n",
679 "[Section name]\n"
680 "MatchVersion=0xFFFFF\n"
681 "ModelAppleTouchpad=1\n",
682 "[Section name]\n"
683 "MatchVersion=123\n"
684 "ModelAppleTouchpad=1\n",
685 };
686 const char **qf;
687
688 ARRAY_FOR_EACH(quirks_file, qf) {
689 struct data_dir dd = make_data_dir(*qf);
690
691 ctx = quirks_init_subsystem(dd.dirname,
692 NULL,
693 log_handler,
694 NULL,
695 QLOG_CUSTOM_LOG_PRIORITIES);
696 ck_assert(ctx == NULL);
697 cleanup_data_dir(dd);
698 }
699 }
700 END_TEST
701
START_TEST(quirks_parse_name)702 START_TEST(quirks_parse_name)
703 {
704 struct quirks_context *ctx;
705 const char quirks_file[] =
706 "[Section name]\n"
707 "MatchName=1235\n"
708 "ModelAppleTouchpad=1\n"
709 "\n"
710 "[Section name]\n"
711 "MatchName=abc\n"
712 "ModelAppleTouchpad=1\n"
713 "\n"
714 "[Section name]\n"
715 "MatchName=*foo\n"
716 "ModelAppleTouchpad=1\n"
717 "\n"
718 "[Section name]\n"
719 "MatchName=foo*\n"
720 "ModelAppleTouchpad=1\n"
721 "\n"
722 "[Section name]\n"
723 "MatchName=foo[]\n"
724 "ModelAppleTouchpad=1\n"
725 "\n"
726 "[Section name]\n"
727 "MatchName=*foo*\n"
728 "ModelAppleTouchpad=1\n";
729 struct data_dir dd = make_data_dir(quirks_file);
730
731 ctx = quirks_init_subsystem(dd.dirname,
732 NULL,
733 log_handler,
734 NULL,
735 QLOG_CUSTOM_LOG_PRIORITIES);
736 ck_assert_notnull(ctx);
737 quirks_context_unref(ctx);
738 cleanup_data_dir(dd);
739 }
740 END_TEST
741
START_TEST(quirks_parse_name_invalid)742 START_TEST(quirks_parse_name_invalid)
743 {
744 struct quirks_context *ctx;
745 const char *quirks_file[] = {
746 "[Section name]\n"
747 "MatchName=\n"
748 "ModelAppleTouchpad=1\n",
749 };
750 const char **qf;
751
752 ARRAY_FOR_EACH(quirks_file, qf) {
753 struct data_dir dd = make_data_dir(*qf);
754
755 ctx = quirks_init_subsystem(dd.dirname,
756 NULL,
757 log_handler,
758 NULL,
759 QLOG_CUSTOM_LOG_PRIORITIES);
760 ck_assert(ctx == NULL);
761 cleanup_data_dir(dd);
762 }
763 }
764 END_TEST
765
START_TEST(quirks_parse_udev)766 START_TEST(quirks_parse_udev)
767 {
768 struct quirks_context *ctx;
769 const char quirks_file[] =
770 "[Section name]\n"
771 "MatchUdevType=touchpad\n"
772 "ModelAppleTouchpad=1\n"
773 "\n"
774 "[Section name]\n"
775 "MatchUdevType=mouse\n"
776 "ModelAppleTouchpad=1\n"
777 "\n"
778 "[Section name]\n"
779 "MatchUdevType=pointingstick\n"
780 "ModelAppleTouchpad=1\n"
781 "\n"
782 "[Section name]\n"
783 "MatchUdevType=tablet\n"
784 "ModelAppleTouchpad=1\n"
785 "\n"
786 "[Section name]\n"
787 "MatchUdevType=tablet-pad\n"
788 "ModelAppleTouchpad=1\n"
789 "\n"
790 "[Section name]\n"
791 "MatchUdevType=keyboard\n"
792 "ModelAppleTouchpad=1\n"
793 "\n"
794 "[Section name]\n"
795 "MatchUdevType=joystick\n"
796 "ModelAppleTouchpad=1\n";
797 struct data_dir dd = make_data_dir(quirks_file);
798
799 ctx = quirks_init_subsystem(dd.dirname,
800 NULL,
801 log_handler,
802 NULL,
803 QLOG_CUSTOM_LOG_PRIORITIES);
804 ck_assert_notnull(ctx);
805 quirks_context_unref(ctx);
806 cleanup_data_dir(dd);
807 }
808 END_TEST
809
START_TEST(quirks_parse_udev_invalid)810 START_TEST(quirks_parse_udev_invalid)
811 {
812 struct quirks_context *ctx;
813 const char *quirks_file[] = {
814 "[Section name]\n"
815 "MatchUdevType=blah\n"
816 "ModelAppleTouchpad=1\n",
817 "[Section name]\n"
818 "MatchUdevType=\n"
819 "ModelAppleTouchpad=1\n",
820 "[Section name]\n"
821 "MatchUdevType=123\n"
822 "ModelAppleTouchpad=1\n",
823 };
824 const char **qf;
825
826 ARRAY_FOR_EACH(quirks_file, qf) {
827 struct data_dir dd = make_data_dir(*qf);
828
829 ctx = quirks_init_subsystem(dd.dirname,
830 NULL,
831 log_handler,
832 NULL,
833 QLOG_CUSTOM_LOG_PRIORITIES);
834 ck_assert(ctx == NULL);
835 cleanup_data_dir(dd);
836 }
837 }
838 END_TEST
839
START_TEST(quirks_parse_dmi)840 START_TEST(quirks_parse_dmi)
841 {
842 struct quirks_context *ctx;
843 const char quirks_file[] =
844 "[Section name]\n"
845 "MatchDMIModalias=dmi:*\n"
846 "ModelAppleTouchpad=1\n"
847 "\n"
848 "[Section name]\n"
849 "MatchDMIModalias=dmi:*svn*pn*:\n"
850 "ModelAppleTouchpad=1\n";
851 struct data_dir dd = make_data_dir(quirks_file);
852
853 ctx = quirks_init_subsystem(dd.dirname,
854 NULL,
855 log_handler,
856 NULL,
857 QLOG_CUSTOM_LOG_PRIORITIES);
858 ck_assert_notnull(ctx);
859 quirks_context_unref(ctx);
860 cleanup_data_dir(dd);
861 }
862 END_TEST
863
START_TEST(quirks_parse_dmi_invalid)864 START_TEST(quirks_parse_dmi_invalid)
865 {
866 struct quirks_context *ctx;
867 const char *quirks_file[] = {
868 "[Section name]\n"
869 "MatchDMIModalias=\n"
870 "ModelAppleTouchpad=1\n",
871 "[Section name]\n"
872 "MatchDMIModalias=*pn*\n"
873 "ModelAppleTouchpad=1\n",
874 "[Section name]\n"
875 "MatchDMIModalias=dmi*pn*\n"
876 "ModelAppleTouchpad=1\n",
877 "[Section name]\n"
878 "MatchDMIModalias=foo\n"
879 "ModelAppleTouchpad=1\n",
880 };
881 const char **qf;
882
883 ARRAY_FOR_EACH(quirks_file, qf) {
884 struct data_dir dd = make_data_dir(*qf);
885
886 ctx = quirks_init_subsystem(dd.dirname,
887 NULL,
888 log_handler,
889 NULL,
890 QLOG_CUSTOM_LOG_PRIORITIES);
891 ck_assert(ctx == NULL);
892 cleanup_data_dir(dd);
893 }
894 }
895 END_TEST
896
897 typedef bool (*qparsefunc) (struct quirks *q, enum quirk which, void* data);
898
899 /*
900 Helper for generic testing, matches on a mouse device with the given
901 quirk set to the given string. Creates a data directory, inits the quirks
902 and calls func() to return the value in data. The func has to take the
903 right data, otherwise boom. Usage:
904 rc = test_attr_parse(dev, QUIRK_ATTR_SIZE_HINT,
905 "10x30", quirks_get_dimensions,
906 &some_struct_quirks_dimensions);
907 if (rc == false) // failed to parse
908 else // struct now contains the 10, 30 values
909 */
910 static bool
test_attr_parse(struct litest_device * dev,enum quirk which,const char * str,qparsefunc func,void * data)911 test_attr_parse(struct litest_device *dev,
912 enum quirk which,
913 const char *str,
914 qparsefunc func,
915 void *data)
916 {
917 struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device);
918 struct quirks_context *ctx;
919 struct data_dir dd;
920 char buf[512];
921 bool result;
922
923 snprintf(buf,
924 sizeof(buf),
925 "[Section name]\n"
926 "MatchUdevType=mouse\n"
927 "%s=%s\n",
928 quirk_get_name(which),
929 str);
930
931 dd = make_data_dir(buf);
932 ctx = quirks_init_subsystem(dd.dirname,
933 NULL,
934 log_handler,
935 NULL,
936 QLOG_CUSTOM_LOG_PRIORITIES);
937 if (ctx != NULL) {
938 struct quirks *q;
939 q = quirks_fetch_for_device(ctx, ud);
940 ck_assert_notnull(q);
941 ck_assert(func(q, which, data));
942 ck_assert(quirks_has_quirk(q, which));
943 quirks_unref(q);
944 quirks_context_unref(ctx);
945 result = true;
946 } else {
947 result = false;
948 }
949
950 cleanup_data_dir(dd);
951 udev_device_unref(ud);
952 return result;
953 }
954
955 struct qtest_dim {
956 const char *str;
957 bool success;
958 int w, h;
959 };
960
START_TEST(quirks_parse_dimension_attr)961 START_TEST(quirks_parse_dimension_attr)
962 {
963 struct litest_device *dev = litest_current_device();
964 enum quirk attrs[] = {
965 QUIRK_ATTR_SIZE_HINT,
966 QUIRK_ATTR_RESOLUTION_HINT,
967 };
968 enum quirk *a;
969 struct qtest_dim test_values[] = {
970 { "10x10", true, 10, 10 },
971 { "20x30", true, 20, 30 },
972 { "-10x30", false, 0, 0 },
973 { "10:30", false, 0, 0 },
974 { "30", false, 0, 0 },
975 { "0x00", false, 0, 0 },
976 { "0xa0", false, 0, 0 },
977 };
978 struct qtest_dim *t;
979
980 ARRAY_FOR_EACH(attrs, a) {
981 ARRAY_FOR_EACH(test_values, t) {
982 struct quirk_dimensions dim;
983 bool rc;
984
985 rc = test_attr_parse(dev,
986 *a,
987 t->str,
988 (qparsefunc)quirks_get_dimensions,
989 &dim);
990 ck_assert_int_eq(rc, t->success);
991 if (!rc)
992 continue;
993
994 ck_assert_int_eq(dim.x, t->w);
995 ck_assert_int_eq(dim.y, t->h);
996 }
997 }
998 }
999 END_TEST
1000
1001 struct qtest_range {
1002 const char *str;
1003 bool success;
1004 int hi, lo;
1005 };
1006
START_TEST(quirks_parse_range_attr)1007 START_TEST(quirks_parse_range_attr)
1008 {
1009 struct litest_device *dev = litest_current_device();
1010 enum quirk attrs[] = {
1011 QUIRK_ATTR_TOUCH_SIZE_RANGE,
1012 QUIRK_ATTR_PRESSURE_RANGE,
1013 };
1014 enum quirk *a;
1015 struct qtest_range test_values[] = {
1016 { "20:10", true, 20, 10 },
1017 { "30:5", true, 30, 5 },
1018 { "30:-10", true, 30, -10 },
1019 { "-30:-100", true, -30, -100 },
1020
1021 { "5:10", false, 0, 0 },
1022 { "5:5", false, 0, 0 },
1023 { "-10:5", false, 0, 0 },
1024 { "-10:-5", false, 0, 0 },
1025 { "10x30", false, 0, 0 },
1026 { "30x10", false, 0, 0 },
1027 { "30", false, 0, 0 },
1028 { "0x00", false, 0, 0 },
1029 { "0xa0", false, 0, 0 },
1030 { "0x10:0x5", false, 0, 0 },
1031 };
1032 struct qtest_range *t;
1033
1034 ARRAY_FOR_EACH(attrs, a) {
1035 ARRAY_FOR_EACH(test_values, t) {
1036 struct quirk_range r;
1037 bool rc;
1038
1039 rc = test_attr_parse(dev,
1040 *a,
1041 t->str,
1042 (qparsefunc)quirks_get_range,
1043 &r);
1044 ck_assert_int_eq(rc, t->success);
1045 if (!rc)
1046 continue;
1047
1048 ck_assert_int_eq(r.lower, t->lo);
1049 ck_assert_int_eq(r.upper, t->hi);
1050 }
1051 }
1052 }
1053 END_TEST
1054
1055 struct qtest_uint {
1056 const char *str;
1057 bool success;
1058 uint32_t val;
1059 };
1060
START_TEST(quirks_parse_uint_attr)1061 START_TEST(quirks_parse_uint_attr)
1062 {
1063 struct litest_device *dev = litest_current_device();
1064 enum quirk attrs[] = {
1065 QUIRK_ATTR_PALM_SIZE_THRESHOLD,
1066 QUIRK_ATTR_PALM_PRESSURE_THRESHOLD,
1067 QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD,
1068 };
1069 enum quirk *a;
1070 struct qtest_uint test_values[] = {
1071 { "10", true, 10 },
1072 { "0", true, 0 },
1073 { "5", true, 5 },
1074 { "65535", true, 65535 },
1075 { "4294967295", true, 4294967295 },
1076 { "-10", false, 0 },
1077 { "0x10", false, 0 },
1078 { "0xab", false, 0 },
1079 { "ab", false, 0 },
1080 };
1081 struct qtest_uint *t;
1082
1083 ARRAY_FOR_EACH(attrs, a) {
1084 ARRAY_FOR_EACH(test_values, t) {
1085 uint32_t v;
1086 bool rc;
1087
1088 rc = test_attr_parse(dev,
1089 *a,
1090 t->str,
1091 (qparsefunc)quirks_get_uint32,
1092 &v);
1093 ck_assert_int_eq(rc, t->success);
1094 if (!rc)
1095 continue;
1096
1097 ck_assert_int_eq(v, t->val);
1098 }
1099 }
1100 }
1101 END_TEST
1102
1103 struct qtest_double {
1104 const char *str;
1105 bool success;
1106 double val;
1107 };
1108
START_TEST(quirks_parse_double_attr)1109 START_TEST(quirks_parse_double_attr)
1110 {
1111 struct litest_device *dev = litest_current_device();
1112 enum quirk attrs[] = {
1113 QUIRK_ATTR_TRACKPOINT_MULTIPLIER,
1114 };
1115 enum quirk *a;
1116 struct qtest_double test_values[] = {
1117 { "10", true, 10.0 },
1118 { "10.0", true, 10.0 },
1119 { "-10.0", true, -10.0 },
1120 { "0", true, 0.0 },
1121 { "0.0", true, 0.0 },
1122 { "5.1", true, 5.1 },
1123 { "-5.9", true, -5.9 },
1124 { "65535", true, 65535 },
1125 { "4294967295", true, 4294967295 },
1126 { "4294967295.123", true, 4294967295.123 },
1127 /* our safe_atoi parses hex even though we don't really want
1128 * to */
1129 { "0x10", false, 0 },
1130 { "0xab", false, 0 },
1131 { "ab", false, 0 },
1132 { "10:5", false, 0 },
1133 { "10x5", false, 0 },
1134 };
1135 struct qtest_double *t;
1136
1137 ARRAY_FOR_EACH(attrs, a) {
1138 ARRAY_FOR_EACH(test_values, t) {
1139 double v;
1140 bool rc;
1141
1142 rc = test_attr_parse(dev,
1143 *a,
1144 t->str,
1145 (qparsefunc)quirks_get_double,
1146 &v);
1147 ck_assert_int_eq(rc, t->success);
1148 if (!rc)
1149 continue;
1150
1151 ck_assert_int_eq(v, t->val);
1152 }
1153 }
1154 }
1155 END_TEST
1156
1157 struct qtest_str {
1158 const char *str;
1159 enum quirk where;
1160 };
1161
START_TEST(quirks_parse_string_attr)1162 START_TEST(quirks_parse_string_attr)
1163 {
1164 struct litest_device *dev = litest_current_device();
1165 enum quirk attrs[] = {
1166 QUIRK_ATTR_TPKBCOMBO_LAYOUT,
1167 QUIRK_ATTR_LID_SWITCH_RELIABILITY,
1168 QUIRK_ATTR_KEYBOARD_INTEGRATION,
1169 };
1170 enum quirk *a;
1171 struct qtest_str test_values[] = {
1172 { "below", QUIRK_ATTR_TPKBCOMBO_LAYOUT },
1173 { "reliable", QUIRK_ATTR_LID_SWITCH_RELIABILITY },
1174 { "write_open", QUIRK_ATTR_LID_SWITCH_RELIABILITY },
1175 { "internal", QUIRK_ATTR_KEYBOARD_INTEGRATION },
1176 { "external", QUIRK_ATTR_KEYBOARD_INTEGRATION },
1177
1178 { "10", 0 },
1179 { "-10", 0 },
1180 { "0", 0 },
1181 { "", 0 },
1182 { "banana", 0 },
1183 { "honk honk", 0 },
1184 { "0x12", 0 },
1185 { "0xa", 0 },
1186 { "0.0", 0 },
1187 };
1188 struct qtest_str *t;
1189
1190 ARRAY_FOR_EACH(attrs, a) {
1191 ARRAY_FOR_EACH(test_values, t) {
1192 bool rc;
1193 char *do_not_use; /* freed before we can use it */
1194
1195 rc = test_attr_parse(dev,
1196 *a,
1197 t->str,
1198 (qparsefunc)quirks_get_string,
1199 &do_not_use);
1200 if (*a == t->where)
1201 ck_assert_int_eq(rc, true);
1202 else
1203 ck_assert_int_eq(rc, false);
1204 }
1205 }
1206 }
1207 END_TEST
1208
1209 struct qtest_bool {
1210 const char *str;
1211 bool success;
1212 bool val;
1213 };
1214
START_TEST(quirks_parse_bool_attr)1215 START_TEST(quirks_parse_bool_attr)
1216 {
1217 struct litest_device *dev = litest_current_device();
1218 enum quirk attrs[] = {
1219 QUIRK_ATTR_USE_VELOCITY_AVERAGING,
1220 QUIRK_ATTR_TABLET_SMOOTHING,
1221 };
1222 enum quirk *a;
1223 struct qtest_bool test_values[] = {
1224 { "0", true, false },
1225 { "1", true, true },
1226 { "2", false, false },
1227 { "-1", false, false },
1228 { "a", false, false },
1229 };
1230 struct qtest_bool *t;
1231
1232 ARRAY_FOR_EACH(attrs, a) {
1233 ARRAY_FOR_EACH(test_values, t) {
1234 bool v;
1235 bool rc;
1236
1237 rc = test_attr_parse(dev,
1238 *a,
1239 t->str,
1240 (qparsefunc)quirks_get_bool,
1241 &v);
1242 ck_assert(rc == t->success);
1243 if (!rc)
1244 continue;
1245
1246 ck_assert(v == t->val);
1247 }
1248 }
1249 }
1250 END_TEST
1251
START_TEST(quirks_parse_integration_attr)1252 START_TEST(quirks_parse_integration_attr)
1253 {
1254 struct litest_device *dev = litest_current_device();
1255 char *do_not_use; /* freed before we can use it */
1256 bool
1257
1258 rc = test_attr_parse(dev,
1259 QUIRK_ATTR_KEYBOARD_INTEGRATION,
1260 "internal",
1261 (qparsefunc)quirks_get_string,
1262 &do_not_use);
1263 ck_assert(rc);
1264 rc = test_attr_parse(dev,
1265 QUIRK_ATTR_KEYBOARD_INTEGRATION,
1266 "external",
1267 (qparsefunc)quirks_get_string,
1268 &do_not_use);
1269 ck_assert(rc);
1270 rc = test_attr_parse(dev,
1271 QUIRK_ATTR_TRACKPOINT_INTEGRATION,
1272 "internal",
1273 (qparsefunc)quirks_get_string,
1274 &do_not_use);
1275 ck_assert(rc);
1276 rc = test_attr_parse(dev,
1277 QUIRK_ATTR_TRACKPOINT_INTEGRATION,
1278 "external",
1279 (qparsefunc)quirks_get_string,
1280 &do_not_use);
1281 ck_assert(rc);
1282 }
1283 END_TEST
1284
START_TEST(quirks_model_one)1285 START_TEST(quirks_model_one)
1286 {
1287 struct litest_device *dev = litest_current_device();
1288 struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device);
1289 struct quirks_context *ctx;
1290 const char quirks_file[] =
1291 "[Section name]\n"
1292 "MatchUdevType=mouse\n"
1293 "ModelAppleTouchpad=1\n";
1294 struct data_dir dd = make_data_dir(quirks_file);
1295 struct quirks *q;
1296 bool isset;
1297
1298 ctx = quirks_init_subsystem(dd.dirname,
1299 NULL,
1300 log_handler,
1301 NULL,
1302 QLOG_CUSTOM_LOG_PRIORITIES);
1303 ck_assert_notnull(ctx);
1304
1305 q = quirks_fetch_for_device(ctx, ud);
1306 ck_assert_notnull(q);
1307
1308 ck_assert(quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &isset));
1309 ck_assert(isset == true);
1310
1311 quirks_unref(q);
1312 quirks_context_unref(ctx);
1313 cleanup_data_dir(dd);
1314 udev_device_unref(ud);
1315 }
1316 END_TEST
1317
START_TEST(quirks_model_zero)1318 START_TEST(quirks_model_zero)
1319 {
1320 struct litest_device *dev = litest_current_device();
1321 struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device);
1322 struct quirks_context *ctx;
1323 const char quirks_file[] =
1324 "[Section name]\n"
1325 "MatchUdevType=mouse\n"
1326 "ModelAppleTouchpad=0\n";
1327 struct data_dir dd = make_data_dir(quirks_file);
1328 struct quirks *q;
1329 bool isset;
1330
1331 ctx = quirks_init_subsystem(dd.dirname,
1332 NULL,
1333 log_handler,
1334 NULL,
1335 QLOG_CUSTOM_LOG_PRIORITIES);
1336 ck_assert_notnull(ctx);
1337
1338 q = quirks_fetch_for_device(ctx, ud);
1339 ck_assert_notnull(q);
1340
1341 ck_assert(quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &isset));
1342 ck_assert(isset == false);
1343
1344 quirks_unref(q);
1345 quirks_context_unref(ctx);
1346 cleanup_data_dir(dd);
1347 udev_device_unref(ud);
1348 }
1349 END_TEST
1350
START_TEST(quirks_model_override)1351 START_TEST(quirks_model_override)
1352 {
1353 struct litest_device *dev = litest_current_device();
1354 struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device);
1355 struct quirks_context *ctx;
1356 char *quirks_file;
1357 struct data_dir dd;
1358 struct quirks *q;
1359 bool isset;
1360 bool set = _i; /* ranged test */
1361
1362 /* Test model quirks override by setting, then unsetting (or the
1363 other way round) */
1364 int rc = xasprintf(&quirks_file,
1365 "[first]\n"
1366 "MatchUdevType=mouse\n"
1367 "ModelAppleTouchpad=%d\n"
1368 "\n"
1369 "[second]\n"
1370 "MatchUdevType=mouse\n"
1371 "ModelAppleTouchpad=%d\n",
1372 set ? 0 : 1,
1373 set ? 1 : 0);
1374 ck_assert_int_ne(rc, -1);
1375
1376 dd = make_data_dir(quirks_file);
1377
1378 ctx = quirks_init_subsystem(dd.dirname,
1379 NULL,
1380 log_handler,
1381 NULL,
1382 QLOG_CUSTOM_LOG_PRIORITIES);
1383 ck_assert_notnull(ctx);
1384
1385 q = quirks_fetch_for_device(ctx, ud);
1386 ck_assert_notnull(q);
1387
1388 ck_assert(quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &isset));
1389 ck_assert(isset == set);
1390
1391 quirks_unref(q);
1392 quirks_context_unref(ctx);
1393 cleanup_data_dir(dd);
1394 udev_device_unref(ud);
1395 free(quirks_file);
1396 }
1397 END_TEST
1398
START_TEST(quirks_model_alps)1399 START_TEST(quirks_model_alps)
1400 {
1401 struct litest_device *dev = litest_current_device();
1402 struct libinput_device *device = dev->libinput_device;
1403 struct quirks *q;
1404 bool exists, value = false;
1405
1406 q = dev->quirks;
1407 exists = quirks_get_bool(q, QUIRK_MODEL_ALPS_SERIAL_TOUCHPAD, &value);
1408
1409 if (strstr(libinput_device_get_name(device), "ALPS")) {
1410 ck_assert(exists);
1411 ck_assert(value);
1412 } else {
1413 ck_assert(!exists);
1414 ck_assert(!value);
1415 }
1416 }
1417 END_TEST
1418
START_TEST(quirks_model_wacom)1419 START_TEST(quirks_model_wacom)
1420 {
1421 struct litest_device *dev = litest_current_device();
1422 struct quirks *q;
1423 bool exists, value = false;
1424
1425 q = dev->quirks;
1426 exists = quirks_get_bool(q, QUIRK_MODEL_WACOM_TOUCHPAD, &value);
1427
1428 if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM) {
1429 ck_assert(exists);
1430 ck_assert(value);
1431 } else {
1432 ck_assert(!exists);
1433 ck_assert(!value);
1434 }
1435 }
1436 END_TEST
1437
START_TEST(quirks_model_apple)1438 START_TEST(quirks_model_apple)
1439 {
1440 struct litest_device *dev = litest_current_device();
1441 struct quirks *q;
1442 bool exists, value = false;
1443
1444 q = dev->quirks;
1445 exists = quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &value);
1446
1447 if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_APPLE) {
1448 ck_assert(exists);
1449 ck_assert(value);
1450 } else {
1451 ck_assert(!exists);
1452 ck_assert(!value);
1453 }
1454 }
1455 END_TEST
1456
START_TEST(quirks_model_synaptics_serial)1457 START_TEST(quirks_model_synaptics_serial)
1458 {
1459 struct litest_device *dev = litest_current_device();
1460 struct quirks *q;
1461 bool exists, value = false;
1462
1463 q = dev->quirks;
1464 exists = quirks_get_bool(q, QUIRK_MODEL_SYNAPTICS_SERIAL_TOUCHPAD, &value);
1465
1466 if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_SYNAPTICS_SERIAL &&
1467 libevdev_get_id_product(dev->evdev) == PRODUCT_ID_SYNAPTICS_SERIAL) {
1468 ck_assert(exists);
1469 ck_assert(value);
1470 } else {
1471 ck_assert(!exists);
1472 ck_assert(!value);
1473 }
1474 }
1475 END_TEST
1476
START_TEST(quirks_call_NULL)1477 START_TEST(quirks_call_NULL)
1478 {
1479 ck_assert(!quirks_fetch_for_device(NULL, NULL));
1480
1481 ck_assert(!quirks_get_uint32(NULL, 0, NULL));
1482 ck_assert(!quirks_get_int32(NULL, 0, NULL));
1483 ck_assert(!quirks_get_range(NULL, 0, NULL));
1484 ck_assert(!quirks_get_dimensions(NULL, 0, NULL));
1485 ck_assert(!quirks_get_double(NULL, 0, NULL));
1486 ck_assert(!quirks_get_string(NULL, 0, NULL));
1487 ck_assert(!quirks_get_bool(NULL, 0, NULL));
1488 }
1489 END_TEST
1490
START_TEST(quirks_ctx_ref)1491 START_TEST(quirks_ctx_ref)
1492 {
1493 struct quirks_context *ctx, *ctx2;
1494 const char quirks_file[] =
1495 "[Section name]\n"
1496 "MatchUdevType=mouse\n"
1497 "AttrSizeHint=10x10\n";
1498 struct data_dir dd = make_data_dir(quirks_file);
1499
1500 ctx = quirks_init_subsystem(dd.dirname,
1501 NULL,
1502 log_handler,
1503 NULL,
1504 QLOG_CUSTOM_LOG_PRIORITIES);
1505 ck_assert_notnull(ctx);
1506 ctx2 = quirks_context_ref(ctx);
1507 litest_assert_ptr_eq(ctx, ctx2);
1508 ctx2 = quirks_context_unref(ctx);
1509 litest_assert_ptr_eq(ctx2, NULL);
1510 ctx2 = quirks_context_unref(ctx);
1511 litest_assert_ptr_eq(ctx2, NULL);
1512 cleanup_data_dir(dd);
1513 }
1514 END_TEST
1515
TEST_COLLECTION(quirks)1516 TEST_COLLECTION(quirks)
1517 {
1518 struct range boolean = {0, 2};
1519
1520 litest_add_deviceless(quirks_invalid_dir);
1521 litest_add_deviceless(quirks_empty_dir);
1522
1523 litest_add_deviceless(quirks_section_empty);
1524 litest_add_deviceless(quirks_section_double);
1525 litest_add_deviceless(quirks_section_missing_match);
1526 litest_add_deviceless(quirks_section_missing_attr);
1527 litest_add_deviceless(quirks_section_match_after_attr);
1528 litest_add_deviceless(quirks_section_duplicate_match);
1529 litest_add_deviceless(quirks_section_duplicate_attr);
1530
1531 litest_add_deviceless(quirks_parse_error_section);
1532 litest_add_deviceless(quirks_parse_error_trailing_whitespace);
1533 litest_add_deviceless(quirks_parse_error_unknown_match);
1534 litest_add_deviceless(quirks_parse_error_unknown_attr);
1535 litest_add_deviceless(quirks_parse_error_unknown_model);
1536 litest_add_deviceless(quirks_parse_error_unknown_prefix);
1537 litest_add_deviceless(quirks_parse_error_model_not_one);
1538 litest_add_deviceless(quirks_parse_comment_inline);
1539 litest_add_deviceless(quirks_parse_comment_empty);
1540 litest_add_deviceless(quirks_parse_string_quotes_single);
1541 litest_add_deviceless(quirks_parse_string_quotes_double);
1542
1543 litest_add_deviceless(quirks_parse_bustype);
1544 litest_add_deviceless(quirks_parse_bustype_invalid);
1545 litest_add_deviceless(quirks_parse_vendor);
1546 litest_add_deviceless(quirks_parse_vendor_invalid);
1547 litest_add_deviceless(quirks_parse_product);
1548 litest_add_deviceless(quirks_parse_product_invalid);
1549 litest_add_deviceless(quirks_parse_version);
1550 litest_add_deviceless(quirks_parse_version_invalid);
1551 litest_add_deviceless(quirks_parse_name);
1552 litest_add_deviceless(quirks_parse_name_invalid);
1553 litest_add_deviceless(quirks_parse_udev);
1554 litest_add_deviceless(quirks_parse_udev_invalid);
1555 litest_add_deviceless(quirks_parse_dmi);
1556 litest_add_deviceless(quirks_parse_dmi_invalid);
1557
1558 litest_add_for_device(quirks_parse_dimension_attr, LITEST_MOUSE);
1559 litest_add_for_device(quirks_parse_range_attr, LITEST_MOUSE);
1560 litest_add_for_device(quirks_parse_uint_attr, LITEST_MOUSE);
1561 litest_add_for_device(quirks_parse_double_attr, LITEST_MOUSE);
1562 litest_add_for_device(quirks_parse_string_attr, LITEST_MOUSE);
1563 litest_add_for_device(quirks_parse_bool_attr, LITEST_MOUSE);
1564 litest_add_for_device(quirks_parse_integration_attr, LITEST_MOUSE);
1565
1566 litest_add_for_device(quirks_model_one, LITEST_MOUSE);
1567 litest_add_for_device(quirks_model_zero, LITEST_MOUSE);
1568 litest_add_ranged_for_device(quirks_model_override, LITEST_MOUSE, &boolean);
1569
1570 litest_add(quirks_model_alps, LITEST_TOUCHPAD, LITEST_ANY);
1571 litest_add(quirks_model_wacom, LITEST_TOUCHPAD, LITEST_ANY);
1572 litest_add(quirks_model_apple, LITEST_TOUCHPAD, LITEST_ANY);
1573 litest_add(quirks_model_synaptics_serial, LITEST_TOUCHPAD, LITEST_ANY);
1574
1575 litest_add_deviceless(quirks_call_NULL);
1576 litest_add_deviceless(quirks_ctx_ref);
1577 }
1578