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
START_TEST(quirks_parse_integration_attr)1209 START_TEST(quirks_parse_integration_attr)
1210 {
1211 struct litest_device *dev = litest_current_device();
1212 char *do_not_use; /* freed before we can use it */
1213 bool
1214
1215 rc = test_attr_parse(dev,
1216 QUIRK_ATTR_KEYBOARD_INTEGRATION,
1217 "internal",
1218 (qparsefunc)quirks_get_string,
1219 &do_not_use);
1220 ck_assert(rc);
1221 rc = test_attr_parse(dev,
1222 QUIRK_ATTR_KEYBOARD_INTEGRATION,
1223 "external",
1224 (qparsefunc)quirks_get_string,
1225 &do_not_use);
1226 ck_assert(rc);
1227 rc = test_attr_parse(dev,
1228 QUIRK_ATTR_TRACKPOINT_INTEGRATION,
1229 "internal",
1230 (qparsefunc)quirks_get_string,
1231 &do_not_use);
1232 ck_assert(rc);
1233 rc = test_attr_parse(dev,
1234 QUIRK_ATTR_TRACKPOINT_INTEGRATION,
1235 "external",
1236 (qparsefunc)quirks_get_string,
1237 &do_not_use);
1238 ck_assert(rc);
1239 }
1240 END_TEST
1241
START_TEST(quirks_model_one)1242 START_TEST(quirks_model_one)
1243 {
1244 struct litest_device *dev = litest_current_device();
1245 struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device);
1246 struct quirks_context *ctx;
1247 const char quirks_file[] =
1248 "[Section name]\n"
1249 "MatchUdevType=mouse\n"
1250 "ModelAppleTouchpad=1\n";
1251 struct data_dir dd = make_data_dir(quirks_file);
1252 struct quirks *q;
1253 bool isset;
1254
1255 ctx = quirks_init_subsystem(dd.dirname,
1256 NULL,
1257 log_handler,
1258 NULL,
1259 QLOG_CUSTOM_LOG_PRIORITIES);
1260 ck_assert_notnull(ctx);
1261
1262 q = quirks_fetch_for_device(ctx, ud);
1263 ck_assert_notnull(q);
1264
1265 ck_assert(quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &isset));
1266 ck_assert(isset == true);
1267
1268 quirks_unref(q);
1269 quirks_context_unref(ctx);
1270 cleanup_data_dir(dd);
1271 udev_device_unref(ud);
1272 }
1273 END_TEST
1274
START_TEST(quirks_model_zero)1275 START_TEST(quirks_model_zero)
1276 {
1277 struct litest_device *dev = litest_current_device();
1278 struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device);
1279 struct quirks_context *ctx;
1280 const char quirks_file[] =
1281 "[Section name]\n"
1282 "MatchUdevType=mouse\n"
1283 "ModelAppleTouchpad=0\n";
1284 struct data_dir dd = make_data_dir(quirks_file);
1285 struct quirks *q;
1286 bool isset;
1287
1288 ctx = quirks_init_subsystem(dd.dirname,
1289 NULL,
1290 log_handler,
1291 NULL,
1292 QLOG_CUSTOM_LOG_PRIORITIES);
1293 ck_assert_notnull(ctx);
1294
1295 q = quirks_fetch_for_device(ctx, ud);
1296 ck_assert_notnull(q);
1297
1298 ck_assert(quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &isset));
1299 ck_assert(isset == false);
1300
1301 quirks_unref(q);
1302 quirks_context_unref(ctx);
1303 cleanup_data_dir(dd);
1304 udev_device_unref(ud);
1305 }
1306 END_TEST
1307
START_TEST(quirks_model_alps)1308 START_TEST(quirks_model_alps)
1309 {
1310 struct litest_device *dev = litest_current_device();
1311 struct libinput_device *device = dev->libinput_device;
1312 struct quirks *q;
1313 bool exists, value = false;
1314
1315 q = dev->quirks;
1316 exists = quirks_get_bool(q, QUIRK_MODEL_ALPS_SERIAL_TOUCHPAD, &value);
1317
1318 if (strstr(libinput_device_get_name(device), "ALPS")) {
1319 ck_assert(exists);
1320 ck_assert(value);
1321 } else {
1322 ck_assert(!exists);
1323 ck_assert(!value);
1324 }
1325 }
1326 END_TEST
1327
START_TEST(quirks_model_wacom)1328 START_TEST(quirks_model_wacom)
1329 {
1330 struct litest_device *dev = litest_current_device();
1331 struct quirks *q;
1332 bool exists, value = false;
1333
1334 q = dev->quirks;
1335 exists = quirks_get_bool(q, QUIRK_MODEL_WACOM_TOUCHPAD, &value);
1336
1337 if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM) {
1338 ck_assert(exists);
1339 ck_assert(value);
1340 } else {
1341 ck_assert(!exists);
1342 ck_assert(!value);
1343 }
1344 }
1345 END_TEST
1346
START_TEST(quirks_model_apple)1347 START_TEST(quirks_model_apple)
1348 {
1349 struct litest_device *dev = litest_current_device();
1350 struct quirks *q;
1351 bool exists, value = false;
1352
1353 q = dev->quirks;
1354 exists = quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &value);
1355
1356 if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_APPLE) {
1357 ck_assert(exists);
1358 ck_assert(value);
1359 } else {
1360 ck_assert(!exists);
1361 ck_assert(!value);
1362 }
1363 }
1364 END_TEST
1365
START_TEST(quirks_model_synaptics_serial)1366 START_TEST(quirks_model_synaptics_serial)
1367 {
1368 struct litest_device *dev = litest_current_device();
1369 struct quirks *q;
1370 bool exists, value = false;
1371
1372 q = dev->quirks;
1373 exists = quirks_get_bool(q, QUIRK_MODEL_SYNAPTICS_SERIAL_TOUCHPAD, &value);
1374
1375 if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_SYNAPTICS_SERIAL &&
1376 libevdev_get_id_product(dev->evdev) == PRODUCT_ID_SYNAPTICS_SERIAL) {
1377 ck_assert(exists);
1378 ck_assert(value);
1379 } else {
1380 ck_assert(!exists);
1381 ck_assert(!value);
1382 }
1383 }
1384 END_TEST
1385
START_TEST(quirks_call_NULL)1386 START_TEST(quirks_call_NULL)
1387 {
1388 ck_assert(!quirks_fetch_for_device(NULL, NULL));
1389
1390 ck_assert(!quirks_get_uint32(NULL, 0, NULL));
1391 ck_assert(!quirks_get_int32(NULL, 0, NULL));
1392 ck_assert(!quirks_get_range(NULL, 0, NULL));
1393 ck_assert(!quirks_get_dimensions(NULL, 0, NULL));
1394 ck_assert(!quirks_get_double(NULL, 0, NULL));
1395 ck_assert(!quirks_get_string(NULL, 0, NULL));
1396 ck_assert(!quirks_get_bool(NULL, 0, NULL));
1397 }
1398 END_TEST
1399
START_TEST(quirks_ctx_ref)1400 START_TEST(quirks_ctx_ref)
1401 {
1402 struct quirks_context *ctx, *ctx2;
1403 const char quirks_file[] =
1404 "[Section name]\n"
1405 "MatchUdevType=mouse\n"
1406 "AttrSizeHint=10x10\n";
1407 struct data_dir dd = make_data_dir(quirks_file);
1408
1409 ctx = quirks_init_subsystem(dd.dirname,
1410 NULL,
1411 log_handler,
1412 NULL,
1413 QLOG_CUSTOM_LOG_PRIORITIES);
1414 ck_assert_notnull(ctx);
1415 ctx2 = quirks_context_ref(ctx);
1416 litest_assert_ptr_eq(ctx, ctx2);
1417 ctx2 = quirks_context_unref(ctx);
1418 litest_assert_ptr_eq(ctx2, NULL);
1419 ctx2 = quirks_context_unref(ctx);
1420 litest_assert_ptr_eq(ctx2, NULL);
1421 cleanup_data_dir(dd);
1422 }
1423 END_TEST
1424
TEST_COLLECTION(quirks)1425 TEST_COLLECTION(quirks)
1426 {
1427 litest_add_deviceless("quirks:datadir", quirks_invalid_dir);
1428 litest_add_deviceless("quirks:datadir", quirks_empty_dir);
1429
1430 litest_add_deviceless("quirks:structure", quirks_section_empty);
1431 litest_add_deviceless("quirks:structure", quirks_section_double);
1432 litest_add_deviceless("quirks:structure", quirks_section_missing_match);
1433 litest_add_deviceless("quirks:structure", quirks_section_missing_attr);
1434 litest_add_deviceless("quirks:structure", quirks_section_match_after_attr);
1435 litest_add_deviceless("quirks:structure", quirks_section_duplicate_match);
1436 litest_add_deviceless("quirks:structure", quirks_section_duplicate_attr);
1437
1438 litest_add_deviceless("quirks:parsing", quirks_parse_error_section);
1439 litest_add_deviceless("quirks:parsing", quirks_parse_error_trailing_whitespace);
1440 litest_add_deviceless("quirks:parsing", quirks_parse_error_unknown_match);
1441 litest_add_deviceless("quirks:parsing", quirks_parse_error_unknown_attr);
1442 litest_add_deviceless("quirks:parsing", quirks_parse_error_unknown_model);
1443 litest_add_deviceless("quirks:parsing", quirks_parse_error_unknown_prefix);
1444 litest_add_deviceless("quirks:parsing", quirks_parse_error_model_not_one);
1445 litest_add_deviceless("quirks:parsing", quirks_parse_comment_inline);
1446 litest_add_deviceless("quirks:parsing", quirks_parse_comment_empty);
1447 litest_add_deviceless("quirks:parsing", quirks_parse_string_quotes_single);
1448 litest_add_deviceless("quirks:parsing", quirks_parse_string_quotes_double);
1449
1450 litest_add_deviceless("quirks:parsing", quirks_parse_bustype);
1451 litest_add_deviceless("quirks:parsing", quirks_parse_bustype_invalid);
1452 litest_add_deviceless("quirks:parsing", quirks_parse_vendor);
1453 litest_add_deviceless("quirks:parsing", quirks_parse_vendor_invalid);
1454 litest_add_deviceless("quirks:parsing", quirks_parse_product);
1455 litest_add_deviceless("quirks:parsing", quirks_parse_product_invalid);
1456 litest_add_deviceless("quirks:parsing", quirks_parse_version);
1457 litest_add_deviceless("quirks:parsing", quirks_parse_version_invalid);
1458 litest_add_deviceless("quirks:parsing", quirks_parse_name);
1459 litest_add_deviceless("quirks:parsing", quirks_parse_name_invalid);
1460 litest_add_deviceless("quirks:parsing", quirks_parse_udev);
1461 litest_add_deviceless("quirks:parsing", quirks_parse_udev_invalid);
1462 litest_add_deviceless("quirks:parsing", quirks_parse_dmi);
1463 litest_add_deviceless("quirks:parsing", quirks_parse_dmi_invalid);
1464
1465 litest_add_for_device("quirks:parsing", quirks_parse_dimension_attr, LITEST_MOUSE);
1466 litest_add_for_device("quirks:parsing", quirks_parse_range_attr, LITEST_MOUSE);
1467 litest_add_for_device("quirks:parsing", quirks_parse_uint_attr, LITEST_MOUSE);
1468 litest_add_for_device("quirks:parsing", quirks_parse_double_attr, LITEST_MOUSE);
1469 litest_add_for_device("quirks:parsing", quirks_parse_string_attr, LITEST_MOUSE);
1470 litest_add_for_device("quirks:parsing", quirks_parse_integration_attr, LITEST_MOUSE);
1471
1472 litest_add_for_device("quirks:model", quirks_model_one, LITEST_MOUSE);
1473 litest_add_for_device("quirks:model", quirks_model_zero, LITEST_MOUSE);
1474
1475 litest_add("quirks:devices", quirks_model_alps, LITEST_TOUCHPAD, LITEST_ANY);
1476 litest_add("quirks:devices", quirks_model_wacom, LITEST_TOUCHPAD, LITEST_ANY);
1477 litest_add("quirks:devices", quirks_model_apple, LITEST_TOUCHPAD, LITEST_ANY);
1478 litest_add("quirks:devices", quirks_model_synaptics_serial, LITEST_TOUCHPAD, LITEST_ANY);
1479
1480 litest_add_deviceless("quirks:misc", quirks_call_NULL);
1481 litest_add_deviceless("quirks:misc", quirks_ctx_ref);
1482 }
1483