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
565 ARRAY_FOR_EACH(quirks_file, qf) {
566 struct data_dir dd = make_data_dir(*qf);
567
568 ctx = quirks_init_subsystem(dd.dirname,
569 NULL,
570 log_handler,
571 NULL,
572 QLOG_CUSTOM_LOG_PRIORITIES);
573 ck_assert(ctx == NULL);
574 cleanup_data_dir(dd);
575 }
576 }
577 END_TEST
578
START_TEST(quirks_parse_product)579 START_TEST(quirks_parse_product)
580 {
581 struct quirks_context *ctx;
582 const char quirks_file[] =
583 "[Section name]\n"
584 "MatchProduct=0x0000\n"
585 "ModelAppleTouchpad=1\n"
586 "\n"
587 "[Section name]\n"
588 "MatchProduct=0x0001\n"
589 "ModelAppleTouchpad=1\n"
590 "\n"
591 "[Section name]\n"
592 "MatchProduct=0x2343\n"
593 "ModelAppleTouchpad=1\n";
594 struct data_dir dd = make_data_dir(quirks_file);
595
596 ctx = quirks_init_subsystem(dd.dirname,
597 NULL,
598 log_handler,
599 NULL,
600 QLOG_CUSTOM_LOG_PRIORITIES);
601 ck_assert_notnull(ctx);
602 quirks_context_unref(ctx);
603 cleanup_data_dir(dd);
604 }
605 END_TEST
606
START_TEST(quirks_parse_product_invalid)607 START_TEST(quirks_parse_product_invalid)
608 {
609 struct quirks_context *ctx;
610 const char *quirks_file[] = {
611 "[Section name]\n"
612 "MatchProduct=-1\n"
613 "ModelAppleTouchpad=1\n",
614 "[Section name]\n"
615 "MatchProduct=abc\n"
616 "ModelAppleTouchpad=1\n",
617 "[Section name]\n"
618 "MatchProduct=0xFFFFF\n"
619 "ModelAppleTouchpad=1\n",
620 "[Section name]\n"
621 "MatchProduct=123\n"
622 "ModelAppleTouchpad=1\n",
623 };
624
625 ARRAY_FOR_EACH(quirks_file, qf) {
626 struct data_dir dd = make_data_dir(*qf);
627
628 ctx = quirks_init_subsystem(dd.dirname,
629 NULL,
630 log_handler,
631 NULL,
632 QLOG_CUSTOM_LOG_PRIORITIES);
633 ck_assert(ctx == NULL);
634 cleanup_data_dir(dd);
635 }
636 }
637 END_TEST
638
START_TEST(quirks_parse_version)639 START_TEST(quirks_parse_version)
640 {
641 struct quirks_context *ctx;
642 const char quirks_file[] =
643 "[Section name]\n"
644 "MatchVersion=0x0000\n"
645 "ModelAppleTouchpad=1\n"
646 "\n"
647 "[Section name]\n"
648 "MatchVersion=0x0001\n"
649 "ModelAppleTouchpad=1\n"
650 "\n"
651 "[Section name]\n"
652 "MatchVersion=0x2343\n"
653 "ModelAppleTouchpad=1\n";
654 struct data_dir dd = make_data_dir(quirks_file);
655
656 ctx = quirks_init_subsystem(dd.dirname,
657 NULL,
658 log_handler,
659 NULL,
660 QLOG_CUSTOM_LOG_PRIORITIES);
661 ck_assert_notnull(ctx);
662 quirks_context_unref(ctx);
663 cleanup_data_dir(dd);
664 }
665 END_TEST
666
START_TEST(quirks_parse_version_invalid)667 START_TEST(quirks_parse_version_invalid)
668 {
669 struct quirks_context *ctx;
670 const char *quirks_file[] = {
671 "[Section name]\n"
672 "MatchVersion=-1\n"
673 "ModelAppleTouchpad=1\n",
674 "[Section name]\n"
675 "MatchVersion=abc\n"
676 "ModelAppleTouchpad=1\n",
677 "[Section name]\n"
678 "MatchVersion=0xFFFFF\n"
679 "ModelAppleTouchpad=1\n",
680 "[Section name]\n"
681 "MatchVersion=123\n"
682 "ModelAppleTouchpad=1\n",
683 };
684
685 ARRAY_FOR_EACH(quirks_file, qf) {
686 struct data_dir dd = make_data_dir(*qf);
687
688 ctx = quirks_init_subsystem(dd.dirname,
689 NULL,
690 log_handler,
691 NULL,
692 QLOG_CUSTOM_LOG_PRIORITIES);
693 ck_assert(ctx == NULL);
694 cleanup_data_dir(dd);
695 }
696 }
697 END_TEST
698
START_TEST(quirks_parse_name)699 START_TEST(quirks_parse_name)
700 {
701 struct quirks_context *ctx;
702 const char quirks_file[] =
703 "[Section name]\n"
704 "MatchName=1235\n"
705 "ModelAppleTouchpad=1\n"
706 "\n"
707 "[Section name]\n"
708 "MatchName=abc\n"
709 "ModelAppleTouchpad=1\n"
710 "\n"
711 "[Section name]\n"
712 "MatchName=*foo\n"
713 "ModelAppleTouchpad=1\n"
714 "\n"
715 "[Section name]\n"
716 "MatchName=foo*\n"
717 "ModelAppleTouchpad=1\n"
718 "\n"
719 "[Section name]\n"
720 "MatchName=foo[]\n"
721 "ModelAppleTouchpad=1\n"
722 "\n"
723 "[Section name]\n"
724 "MatchName=*foo*\n"
725 "ModelAppleTouchpad=1\n";
726 struct data_dir dd = make_data_dir(quirks_file);
727
728 ctx = quirks_init_subsystem(dd.dirname,
729 NULL,
730 log_handler,
731 NULL,
732 QLOG_CUSTOM_LOG_PRIORITIES);
733 ck_assert_notnull(ctx);
734 quirks_context_unref(ctx);
735 cleanup_data_dir(dd);
736 }
737 END_TEST
738
START_TEST(quirks_parse_name_invalid)739 START_TEST(quirks_parse_name_invalid)
740 {
741 struct quirks_context *ctx;
742 const char *quirks_file[] = {
743 "[Section name]\n"
744 "MatchName=\n"
745 "ModelAppleTouchpad=1\n",
746 };
747
748 ARRAY_FOR_EACH(quirks_file, qf) {
749 struct data_dir dd = make_data_dir(*qf);
750
751 ctx = quirks_init_subsystem(dd.dirname,
752 NULL,
753 log_handler,
754 NULL,
755 QLOG_CUSTOM_LOG_PRIORITIES);
756 ck_assert(ctx == NULL);
757 cleanup_data_dir(dd);
758 }
759 }
760 END_TEST
761
START_TEST(quirks_parse_udev)762 START_TEST(quirks_parse_udev)
763 {
764 struct quirks_context *ctx;
765 const char quirks_file[] =
766 "[Section name]\n"
767 "MatchUdevType=touchpad\n"
768 "ModelAppleTouchpad=1\n"
769 "\n"
770 "[Section name]\n"
771 "MatchUdevType=mouse\n"
772 "ModelAppleTouchpad=1\n"
773 "\n"
774 "[Section name]\n"
775 "MatchUdevType=pointingstick\n"
776 "ModelAppleTouchpad=1\n"
777 "\n"
778 "[Section name]\n"
779 "MatchUdevType=tablet\n"
780 "ModelAppleTouchpad=1\n"
781 "\n"
782 "[Section name]\n"
783 "MatchUdevType=tablet-pad\n"
784 "ModelAppleTouchpad=1\n"
785 "\n"
786 "[Section name]\n"
787 "MatchUdevType=keyboard\n"
788 "ModelAppleTouchpad=1\n"
789 "\n"
790 "[Section name]\n"
791 "MatchUdevType=joystick\n"
792 "ModelAppleTouchpad=1\n";
793 struct data_dir dd = make_data_dir(quirks_file);
794
795 ctx = quirks_init_subsystem(dd.dirname,
796 NULL,
797 log_handler,
798 NULL,
799 QLOG_CUSTOM_LOG_PRIORITIES);
800 ck_assert_notnull(ctx);
801 quirks_context_unref(ctx);
802 cleanup_data_dir(dd);
803 }
804 END_TEST
805
START_TEST(quirks_parse_udev_invalid)806 START_TEST(quirks_parse_udev_invalid)
807 {
808 struct quirks_context *ctx;
809 const char *quirks_file[] = {
810 "[Section name]\n"
811 "MatchUdevType=blah\n"
812 "ModelAppleTouchpad=1\n",
813 "[Section name]\n"
814 "MatchUdevType=\n"
815 "ModelAppleTouchpad=1\n",
816 "[Section name]\n"
817 "MatchUdevType=123\n"
818 "ModelAppleTouchpad=1\n",
819 };
820
821 ARRAY_FOR_EACH(quirks_file, qf) {
822 struct data_dir dd = make_data_dir(*qf);
823
824 ctx = quirks_init_subsystem(dd.dirname,
825 NULL,
826 log_handler,
827 NULL,
828 QLOG_CUSTOM_LOG_PRIORITIES);
829 ck_assert(ctx == NULL);
830 cleanup_data_dir(dd);
831 }
832 }
833 END_TEST
834
START_TEST(quirks_parse_dmi)835 START_TEST(quirks_parse_dmi)
836 {
837 struct quirks_context *ctx;
838 const char quirks_file[] =
839 "[Section name]\n"
840 "MatchDMIModalias=dmi:*\n"
841 "ModelAppleTouchpad=1\n"
842 "\n"
843 "[Section name]\n"
844 "MatchDMIModalias=dmi:*svn*pn*:\n"
845 "ModelAppleTouchpad=1\n";
846 struct data_dir dd = make_data_dir(quirks_file);
847
848 ctx = quirks_init_subsystem(dd.dirname,
849 NULL,
850 log_handler,
851 NULL,
852 QLOG_CUSTOM_LOG_PRIORITIES);
853 ck_assert_notnull(ctx);
854 quirks_context_unref(ctx);
855 cleanup_data_dir(dd);
856 }
857 END_TEST
858
START_TEST(quirks_parse_dmi_invalid)859 START_TEST(quirks_parse_dmi_invalid)
860 {
861 struct quirks_context *ctx;
862 const char *quirks_file[] = {
863 "[Section name]\n"
864 "MatchDMIModalias=\n"
865 "ModelAppleTouchpad=1\n",
866 "[Section name]\n"
867 "MatchDMIModalias=*pn*\n"
868 "ModelAppleTouchpad=1\n",
869 "[Section name]\n"
870 "MatchDMIModalias=dmi*pn*\n"
871 "ModelAppleTouchpad=1\n",
872 "[Section name]\n"
873 "MatchDMIModalias=foo\n"
874 "ModelAppleTouchpad=1\n",
875 };
876
877 ARRAY_FOR_EACH(quirks_file, qf) {
878 struct data_dir dd = make_data_dir(*qf);
879
880 ctx = quirks_init_subsystem(dd.dirname,
881 NULL,
882 log_handler,
883 NULL,
884 QLOG_CUSTOM_LOG_PRIORITIES);
885 ck_assert(ctx == NULL);
886 cleanup_data_dir(dd);
887 }
888 }
889 END_TEST
890
891 typedef bool (*qparsefunc) (struct quirks *q, enum quirk which, void* data);
892
893 /*
894 Helper for generic testing, matches on a mouse device with the given
895 quirk set to the given string. Creates a data directory, inits the quirks
896 and calls func() to return the value in data. The func has to take the
897 right data, otherwise boom. Usage:
898 rc = test_attr_parse(dev, QUIRK_ATTR_SIZE_HINT,
899 "10x30", quirks_get_dimensions,
900 &some_struct_quirks_dimensions);
901 if (rc == false) // failed to parse
902 else // struct now contains the 10, 30 values
903 */
904 static bool
test_attr_parse(struct litest_device * dev,enum quirk which,const char * str,qparsefunc func,void * data)905 test_attr_parse(struct litest_device *dev,
906 enum quirk which,
907 const char *str,
908 qparsefunc func,
909 void *data)
910 {
911 struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device);
912 struct quirks_context *ctx;
913 struct data_dir dd;
914 char buf[512];
915 bool result;
916
917 snprintf(buf,
918 sizeof(buf),
919 "[Section name]\n"
920 "MatchUdevType=mouse\n"
921 "%s=%s\n",
922 quirk_get_name(which),
923 str);
924
925 dd = make_data_dir(buf);
926 ctx = quirks_init_subsystem(dd.dirname,
927 NULL,
928 log_handler,
929 NULL,
930 QLOG_CUSTOM_LOG_PRIORITIES);
931 if (ctx != NULL) {
932 struct quirks *q;
933 q = quirks_fetch_for_device(ctx, ud);
934 ck_assert_notnull(q);
935 ck_assert(func(q, which, data));
936 ck_assert(quirks_has_quirk(q, which));
937 quirks_unref(q);
938 quirks_context_unref(ctx);
939 result = true;
940 } else {
941 result = false;
942 }
943
944 cleanup_data_dir(dd);
945 udev_device_unref(ud);
946 return result;
947 }
948
949 struct qtest_dim {
950 const char *str;
951 bool success;
952 int w, h;
953 };
954
START_TEST(quirks_parse_dimension_attr)955 START_TEST(quirks_parse_dimension_attr)
956 {
957 struct litest_device *dev = litest_current_device();
958 enum quirk attrs[] = {
959 QUIRK_ATTR_SIZE_HINT,
960 QUIRK_ATTR_RESOLUTION_HINT,
961 };
962 struct qtest_dim test_values[] = {
963 { "10x10", true, 10, 10 },
964 { "20x30", true, 20, 30 },
965 { "-10x30", false, 0, 0 },
966 { "10:30", false, 0, 0 },
967 { "30", false, 0, 0 },
968 { "0x00", false, 0, 0 },
969 { "0xa0", false, 0, 0 },
970 };
971
972 ARRAY_FOR_EACH(attrs, a) {
973 ARRAY_FOR_EACH(test_values, t) {
974 struct quirk_dimensions dim;
975 bool rc;
976
977 rc = test_attr_parse(dev,
978 *a,
979 t->str,
980 (qparsefunc)quirks_get_dimensions,
981 &dim);
982 ck_assert_int_eq(rc, t->success);
983 if (!rc)
984 continue;
985
986 ck_assert_int_eq(dim.x, t->w);
987 ck_assert_int_eq(dim.y, t->h);
988 }
989 }
990 }
991 END_TEST
992
993 struct qtest_range {
994 const char *str;
995 bool success;
996 int hi, lo;
997 };
998
START_TEST(quirks_parse_range_attr)999 START_TEST(quirks_parse_range_attr)
1000 {
1001 struct litest_device *dev = litest_current_device();
1002 enum quirk attrs[] = {
1003 QUIRK_ATTR_TOUCH_SIZE_RANGE,
1004 QUIRK_ATTR_PRESSURE_RANGE,
1005 };
1006 struct qtest_range test_values[] = {
1007 { "20:10", true, 20, 10 },
1008 { "30:5", true, 30, 5 },
1009 { "30:-10", true, 30, -10 },
1010 { "-30:-100", true, -30, -100 },
1011
1012 { "5:10", false, 0, 0 },
1013 { "5:5", false, 0, 0 },
1014 { "-10:5", false, 0, 0 },
1015 { "-10:-5", false, 0, 0 },
1016 { "10x30", false, 0, 0 },
1017 { "30x10", false, 0, 0 },
1018 { "30", false, 0, 0 },
1019 { "0x00", false, 0, 0 },
1020 { "0xa0", false, 0, 0 },
1021 { "0x10:0x5", false, 0, 0 },
1022 };
1023
1024 ARRAY_FOR_EACH(attrs, a) {
1025 ARRAY_FOR_EACH(test_values, t) {
1026 struct quirk_range r;
1027 bool rc;
1028
1029 rc = test_attr_parse(dev,
1030 *a,
1031 t->str,
1032 (qparsefunc)quirks_get_range,
1033 &r);
1034 ck_assert_int_eq(rc, t->success);
1035 if (!rc)
1036 continue;
1037
1038 ck_assert_int_eq(r.lower, t->lo);
1039 ck_assert_int_eq(r.upper, t->hi);
1040 }
1041 }
1042 }
1043 END_TEST
1044
1045 struct qtest_uint {
1046 const char *str;
1047 bool success;
1048 uint32_t val;
1049 };
1050
START_TEST(quirks_parse_uint_attr)1051 START_TEST(quirks_parse_uint_attr)
1052 {
1053 struct litest_device *dev = litest_current_device();
1054 enum quirk attrs[] = {
1055 QUIRK_ATTR_PALM_SIZE_THRESHOLD,
1056 QUIRK_ATTR_PALM_PRESSURE_THRESHOLD,
1057 QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD,
1058 };
1059 struct qtest_uint test_values[] = {
1060 { "10", true, 10 },
1061 { "0", true, 0 },
1062 { "5", true, 5 },
1063 { "65535", true, 65535 },
1064 { "4294967295", true, 4294967295 },
1065 { "-10", false, 0 },
1066 { "0x10", false, 0 },
1067 { "0xab", false, 0 },
1068 { "ab", false, 0 },
1069 };
1070
1071 ARRAY_FOR_EACH(attrs, a) {
1072 ARRAY_FOR_EACH(test_values, t) {
1073 uint32_t v;
1074 bool rc;
1075
1076 rc = test_attr_parse(dev,
1077 *a,
1078 t->str,
1079 (qparsefunc)quirks_get_uint32,
1080 &v);
1081 ck_assert_int_eq(rc, t->success);
1082 if (!rc)
1083 continue;
1084
1085 ck_assert_int_eq(v, t->val);
1086 }
1087 }
1088 }
1089 END_TEST
1090
1091 struct qtest_double {
1092 const char *str;
1093 bool success;
1094 double val;
1095 };
1096
START_TEST(quirks_parse_double_attr)1097 START_TEST(quirks_parse_double_attr)
1098 {
1099 struct litest_device *dev = litest_current_device();
1100 enum quirk attrs[] = {
1101 QUIRK_ATTR_TRACKPOINT_MULTIPLIER,
1102 };
1103 struct qtest_double test_values[] = {
1104 { "10", true, 10.0 },
1105 { "10.0", true, 10.0 },
1106 { "-10.0", true, -10.0 },
1107 { "0", true, 0.0 },
1108 { "0.0", true, 0.0 },
1109 { "5.1", true, 5.1 },
1110 { "-5.9", true, -5.9 },
1111 { "65535", true, 65535 },
1112 { "4294967295", true, 4294967295 },
1113 { "4294967295.123", true, 4294967295.123 },
1114 /* our safe_atoi parses hex even though we don't really want
1115 * to */
1116 { "0x10", false, 0 },
1117 { "0xab", false, 0 },
1118 { "ab", false, 0 },
1119 { "10:5", false, 0 },
1120 { "10x5", false, 0 },
1121 };
1122
1123 ARRAY_FOR_EACH(attrs, a) {
1124 ARRAY_FOR_EACH(test_values, t) {
1125 double v;
1126 bool rc;
1127
1128 rc = test_attr_parse(dev,
1129 *a,
1130 t->str,
1131 (qparsefunc)quirks_get_double,
1132 &v);
1133 ck_assert_int_eq(rc, t->success);
1134 if (!rc)
1135 continue;
1136
1137 ck_assert_int_eq(v, t->val);
1138 }
1139 }
1140 }
1141 END_TEST
1142
1143 struct qtest_str {
1144 const char *str;
1145 enum quirk where;
1146 };
1147
START_TEST(quirks_parse_string_attr)1148 START_TEST(quirks_parse_string_attr)
1149 {
1150 struct litest_device *dev = litest_current_device();
1151 enum quirk attrs[] = {
1152 QUIRK_ATTR_TPKBCOMBO_LAYOUT,
1153 QUIRK_ATTR_LID_SWITCH_RELIABILITY,
1154 QUIRK_ATTR_KEYBOARD_INTEGRATION,
1155 };
1156 struct qtest_str test_values[] = {
1157 { "below", QUIRK_ATTR_TPKBCOMBO_LAYOUT },
1158 { "reliable", QUIRK_ATTR_LID_SWITCH_RELIABILITY },
1159 { "write_open", QUIRK_ATTR_LID_SWITCH_RELIABILITY },
1160 { "internal", QUIRK_ATTR_KEYBOARD_INTEGRATION },
1161 { "external", QUIRK_ATTR_KEYBOARD_INTEGRATION },
1162
1163 { "10", 0 },
1164 { "-10", 0 },
1165 { "0", 0 },
1166 { "", 0 },
1167 { "banana", 0 },
1168 { "honk honk", 0 },
1169 { "0x12", 0 },
1170 { "0xa", 0 },
1171 { "0.0", 0 },
1172 };
1173
1174 ARRAY_FOR_EACH(attrs, a) {
1175 ARRAY_FOR_EACH(test_values, t) {
1176 bool rc;
1177 char *do_not_use; /* freed before we can use it */
1178
1179 rc = test_attr_parse(dev,
1180 *a,
1181 t->str,
1182 (qparsefunc)quirks_get_string,
1183 &do_not_use);
1184 if (*a == t->where)
1185 ck_assert_int_eq(rc, true);
1186 else
1187 ck_assert_int_eq(rc, false);
1188 }
1189 }
1190 }
1191 END_TEST
1192
1193 struct qtest_bool {
1194 const char *str;
1195 bool success;
1196 bool val;
1197 };
1198
START_TEST(quirks_parse_bool_attr)1199 START_TEST(quirks_parse_bool_attr)
1200 {
1201 struct litest_device *dev = litest_current_device();
1202 enum quirk attrs[] = {
1203 QUIRK_ATTR_USE_VELOCITY_AVERAGING,
1204 QUIRK_ATTR_TABLET_SMOOTHING,
1205 };
1206 struct qtest_bool test_values[] = {
1207 { "0", true, false },
1208 { "1", true, true },
1209 { "2", false, false },
1210 { "-1", false, false },
1211 { "a", false, false },
1212 };
1213
1214 ARRAY_FOR_EACH(attrs, a) {
1215 ARRAY_FOR_EACH(test_values, t) {
1216 bool v;
1217 bool rc;
1218
1219 rc = test_attr_parse(dev,
1220 *a,
1221 t->str,
1222 (qparsefunc)quirks_get_bool,
1223 &v);
1224 ck_assert(rc == t->success);
1225 if (!rc)
1226 continue;
1227
1228 ck_assert(v == t->val);
1229 }
1230 }
1231 }
1232 END_TEST
1233
START_TEST(quirks_parse_integration_attr)1234 START_TEST(quirks_parse_integration_attr)
1235 {
1236 struct litest_device *dev = litest_current_device();
1237 char *do_not_use; /* freed before we can use it */
1238 bool
1239
1240 rc = test_attr_parse(dev,
1241 QUIRK_ATTR_KEYBOARD_INTEGRATION,
1242 "internal",
1243 (qparsefunc)quirks_get_string,
1244 &do_not_use);
1245 ck_assert(rc);
1246 rc = test_attr_parse(dev,
1247 QUIRK_ATTR_KEYBOARD_INTEGRATION,
1248 "external",
1249 (qparsefunc)quirks_get_string,
1250 &do_not_use);
1251 ck_assert(rc);
1252 rc = test_attr_parse(dev,
1253 QUIRK_ATTR_TRACKPOINT_INTEGRATION,
1254 "internal",
1255 (qparsefunc)quirks_get_string,
1256 &do_not_use);
1257 ck_assert(rc);
1258 rc = test_attr_parse(dev,
1259 QUIRK_ATTR_TRACKPOINT_INTEGRATION,
1260 "external",
1261 (qparsefunc)quirks_get_string,
1262 &do_not_use);
1263 ck_assert(rc);
1264 }
1265 END_TEST
1266
START_TEST(quirks_model_one)1267 START_TEST(quirks_model_one)
1268 {
1269 struct litest_device *dev = litest_current_device();
1270 struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device);
1271 struct quirks_context *ctx;
1272 const char quirks_file[] =
1273 "[Section name]\n"
1274 "MatchUdevType=mouse\n"
1275 "ModelAppleTouchpad=1\n";
1276 struct data_dir dd = make_data_dir(quirks_file);
1277 struct quirks *q;
1278 bool isset;
1279
1280 ctx = quirks_init_subsystem(dd.dirname,
1281 NULL,
1282 log_handler,
1283 NULL,
1284 QLOG_CUSTOM_LOG_PRIORITIES);
1285 ck_assert_notnull(ctx);
1286
1287 q = quirks_fetch_for_device(ctx, ud);
1288 ck_assert_notnull(q);
1289
1290 ck_assert(quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &isset));
1291 ck_assert(isset == true);
1292
1293 quirks_unref(q);
1294 quirks_context_unref(ctx);
1295 cleanup_data_dir(dd);
1296 udev_device_unref(ud);
1297 }
1298 END_TEST
1299
START_TEST(quirks_model_zero)1300 START_TEST(quirks_model_zero)
1301 {
1302 struct litest_device *dev = litest_current_device();
1303 struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device);
1304 struct quirks_context *ctx;
1305 const char quirks_file[] =
1306 "[Section name]\n"
1307 "MatchUdevType=mouse\n"
1308 "ModelAppleTouchpad=0\n";
1309 struct data_dir dd = make_data_dir(quirks_file);
1310 struct quirks *q;
1311 bool isset;
1312
1313 ctx = quirks_init_subsystem(dd.dirname,
1314 NULL,
1315 log_handler,
1316 NULL,
1317 QLOG_CUSTOM_LOG_PRIORITIES);
1318 ck_assert_notnull(ctx);
1319
1320 q = quirks_fetch_for_device(ctx, ud);
1321 ck_assert_notnull(q);
1322
1323 ck_assert(quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &isset));
1324 ck_assert(isset == false);
1325
1326 quirks_unref(q);
1327 quirks_context_unref(ctx);
1328 cleanup_data_dir(dd);
1329 udev_device_unref(ud);
1330 }
1331 END_TEST
1332
START_TEST(quirks_model_override)1333 START_TEST(quirks_model_override)
1334 {
1335 struct litest_device *dev = litest_current_device();
1336 struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device);
1337 struct quirks_context *ctx;
1338 char *quirks_file;
1339 struct data_dir dd;
1340 struct quirks *q;
1341 bool isset;
1342 bool set = _i; /* ranged test */
1343
1344 /* Test model quirks override by setting, then unsetting (or the
1345 other way round) */
1346 int rc = xasprintf(&quirks_file,
1347 "[first]\n"
1348 "MatchUdevType=mouse\n"
1349 "ModelAppleTouchpad=%d\n"
1350 "\n"
1351 "[second]\n"
1352 "MatchUdevType=mouse\n"
1353 "ModelAppleTouchpad=%d\n",
1354 set ? 0 : 1,
1355 set ? 1 : 0);
1356 ck_assert_int_ne(rc, -1);
1357
1358 dd = make_data_dir(quirks_file);
1359
1360 ctx = quirks_init_subsystem(dd.dirname,
1361 NULL,
1362 log_handler,
1363 NULL,
1364 QLOG_CUSTOM_LOG_PRIORITIES);
1365 ck_assert_notnull(ctx);
1366
1367 q = quirks_fetch_for_device(ctx, ud);
1368 ck_assert_notnull(q);
1369
1370 ck_assert(quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &isset));
1371 ck_assert(isset == set);
1372
1373 quirks_unref(q);
1374 quirks_context_unref(ctx);
1375 cleanup_data_dir(dd);
1376 udev_device_unref(ud);
1377 free(quirks_file);
1378 }
1379 END_TEST
1380
START_TEST(quirks_model_alps)1381 START_TEST(quirks_model_alps)
1382 {
1383 struct litest_device *dev = litest_current_device();
1384 struct libinput_device *device = dev->libinput_device;
1385 struct quirks *q;
1386 bool exists, value = false;
1387
1388 q = dev->quirks;
1389 exists = quirks_get_bool(q, QUIRK_MODEL_ALPS_SERIAL_TOUCHPAD, &value);
1390
1391 if (strstr(libinput_device_get_name(device), "ALPS")) {
1392 ck_assert(exists);
1393 ck_assert(value);
1394 } else {
1395 ck_assert(!exists);
1396 ck_assert(!value);
1397 }
1398 }
1399 END_TEST
1400
START_TEST(quirks_model_wacom)1401 START_TEST(quirks_model_wacom)
1402 {
1403 struct litest_device *dev = litest_current_device();
1404 struct quirks *q;
1405 bool exists, value = false;
1406
1407 q = dev->quirks;
1408 exists = quirks_get_bool(q, QUIRK_MODEL_WACOM_TOUCHPAD, &value);
1409
1410 if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM) {
1411 ck_assert(exists);
1412 ck_assert(value);
1413 } else {
1414 ck_assert(!exists);
1415 ck_assert(!value);
1416 }
1417 }
1418 END_TEST
1419
START_TEST(quirks_model_apple)1420 START_TEST(quirks_model_apple)
1421 {
1422 struct litest_device *dev = litest_current_device();
1423 struct quirks *q;
1424 bool exists, value = false;
1425
1426 q = dev->quirks;
1427 exists = quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &value);
1428
1429 if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_APPLE) {
1430 ck_assert(exists);
1431 ck_assert(value);
1432 } else {
1433 ck_assert(!exists);
1434 ck_assert(!value);
1435 }
1436 }
1437 END_TEST
1438
START_TEST(quirks_model_synaptics_serial)1439 START_TEST(quirks_model_synaptics_serial)
1440 {
1441 struct litest_device *dev = litest_current_device();
1442 struct quirks *q;
1443 bool exists, value = false;
1444
1445 q = dev->quirks;
1446 exists = quirks_get_bool(q, QUIRK_MODEL_SYNAPTICS_SERIAL_TOUCHPAD, &value);
1447
1448 if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_SYNAPTICS_SERIAL &&
1449 libevdev_get_id_product(dev->evdev) == PRODUCT_ID_SYNAPTICS_SERIAL) {
1450 ck_assert(exists);
1451 ck_assert(value);
1452 } else {
1453 ck_assert(!exists);
1454 ck_assert(!value);
1455 }
1456 }
1457 END_TEST
1458
START_TEST(quirks_call_NULL)1459 START_TEST(quirks_call_NULL)
1460 {
1461 ck_assert(!quirks_fetch_for_device(NULL, NULL));
1462
1463 ck_assert(!quirks_get_uint32(NULL, 0, NULL));
1464 ck_assert(!quirks_get_int32(NULL, 0, NULL));
1465 ck_assert(!quirks_get_range(NULL, 0, NULL));
1466 ck_assert(!quirks_get_dimensions(NULL, 0, NULL));
1467 ck_assert(!quirks_get_double(NULL, 0, NULL));
1468 ck_assert(!quirks_get_string(NULL, 0, NULL));
1469 ck_assert(!quirks_get_bool(NULL, 0, NULL));
1470 }
1471 END_TEST
1472
START_TEST(quirks_ctx_ref)1473 START_TEST(quirks_ctx_ref)
1474 {
1475 struct quirks_context *ctx, *ctx2;
1476 const char quirks_file[] =
1477 "[Section name]\n"
1478 "MatchUdevType=mouse\n"
1479 "AttrSizeHint=10x10\n";
1480 struct data_dir dd = make_data_dir(quirks_file);
1481
1482 ctx = quirks_init_subsystem(dd.dirname,
1483 NULL,
1484 log_handler,
1485 NULL,
1486 QLOG_CUSTOM_LOG_PRIORITIES);
1487 ck_assert_notnull(ctx);
1488 ctx2 = quirks_context_ref(ctx);
1489 litest_assert_ptr_eq(ctx, ctx2);
1490 ctx2 = quirks_context_unref(ctx);
1491 litest_assert_ptr_eq(ctx2, NULL);
1492 ctx2 = quirks_context_unref(ctx);
1493 litest_assert_ptr_eq(ctx2, NULL);
1494 cleanup_data_dir(dd);
1495 }
1496 END_TEST
1497
TEST_COLLECTION(quirks)1498 TEST_COLLECTION(quirks)
1499 {
1500 struct range boolean = {0, 2};
1501
1502 litest_add_deviceless(quirks_invalid_dir);
1503 litest_add_deviceless(quirks_empty_dir);
1504
1505 litest_add_deviceless(quirks_section_empty);
1506 litest_add_deviceless(quirks_section_double);
1507 litest_add_deviceless(quirks_section_missing_match);
1508 litest_add_deviceless(quirks_section_missing_attr);
1509 litest_add_deviceless(quirks_section_match_after_attr);
1510 litest_add_deviceless(quirks_section_duplicate_match);
1511 litest_add_deviceless(quirks_section_duplicate_attr);
1512
1513 litest_add_deviceless(quirks_parse_error_section);
1514 litest_add_deviceless(quirks_parse_error_trailing_whitespace);
1515 litest_add_deviceless(quirks_parse_error_unknown_match);
1516 litest_add_deviceless(quirks_parse_error_unknown_attr);
1517 litest_add_deviceless(quirks_parse_error_unknown_model);
1518 litest_add_deviceless(quirks_parse_error_unknown_prefix);
1519 litest_add_deviceless(quirks_parse_error_model_not_one);
1520 litest_add_deviceless(quirks_parse_comment_inline);
1521 litest_add_deviceless(quirks_parse_comment_empty);
1522 litest_add_deviceless(quirks_parse_string_quotes_single);
1523 litest_add_deviceless(quirks_parse_string_quotes_double);
1524
1525 litest_add_deviceless(quirks_parse_bustype);
1526 litest_add_deviceless(quirks_parse_bustype_invalid);
1527 litest_add_deviceless(quirks_parse_vendor);
1528 litest_add_deviceless(quirks_parse_vendor_invalid);
1529 litest_add_deviceless(quirks_parse_product);
1530 litest_add_deviceless(quirks_parse_product_invalid);
1531 litest_add_deviceless(quirks_parse_version);
1532 litest_add_deviceless(quirks_parse_version_invalid);
1533 litest_add_deviceless(quirks_parse_name);
1534 litest_add_deviceless(quirks_parse_name_invalid);
1535 litest_add_deviceless(quirks_parse_udev);
1536 litest_add_deviceless(quirks_parse_udev_invalid);
1537 litest_add_deviceless(quirks_parse_dmi);
1538 litest_add_deviceless(quirks_parse_dmi_invalid);
1539
1540 litest_add_for_device(quirks_parse_dimension_attr, LITEST_MOUSE);
1541 litest_add_for_device(quirks_parse_range_attr, LITEST_MOUSE);
1542 litest_add_for_device(quirks_parse_uint_attr, LITEST_MOUSE);
1543 litest_add_for_device(quirks_parse_double_attr, LITEST_MOUSE);
1544 litest_add_for_device(quirks_parse_string_attr, LITEST_MOUSE);
1545 litest_add_for_device(quirks_parse_bool_attr, LITEST_MOUSE);
1546 litest_add_for_device(quirks_parse_integration_attr, LITEST_MOUSE);
1547
1548 litest_add_for_device(quirks_model_one, LITEST_MOUSE);
1549 litest_add_for_device(quirks_model_zero, LITEST_MOUSE);
1550 litest_add_ranged_for_device(quirks_model_override, LITEST_MOUSE, &boolean);
1551
1552 litest_add(quirks_model_alps, LITEST_TOUCHPAD, LITEST_ANY);
1553 litest_add(quirks_model_wacom, LITEST_TOUCHPAD, LITEST_ANY);
1554 litest_add(quirks_model_apple, LITEST_TOUCHPAD, LITEST_ANY);
1555 litest_add(quirks_model_synaptics_serial, LITEST_TOUCHPAD, LITEST_ANY);
1556
1557 litest_add_deviceless(quirks_call_NULL);
1558 litest_add_deviceless(quirks_ctx_ref);
1559 }
1560