1 /*
2 * Copyright © 2014 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
28 #include <valgrind/valgrind.h>
29
30 #include "util-list.h"
31 #include "util-strings.h"
32 #include "util-time.h"
33 #include "util-prop-parsers.h"
34 #include "util-macros.h"
35 #include "util-bits.h"
36 #include "util-ratelimit.h"
37 #include "util-matrix.h"
38
39 #define TEST_VERSIONSORT
40 #include "libinput-versionsort.h"
41
42 #include "check-double-macros.h"
43
START_TESTnull44 START_TEST(array_for_each)
45 {
46 int ai[6];
47 char ac[10];
48 struct as {
49 int a;
50 char b;
51 int *ptr;
52 } as[32];
53
54 for (size_t i = 0; i < 6; i++)
55 ai[i] = 20 + i;
56 for (size_t i = 0; i < 10; i++)
57 ac[i] = 100 + i;
58 for (size_t i = 0; i < 32; i++) {
59 as[i].a = 10 + i;
60 as[i].b = 20 + i;
61 as[i].ptr = (int*)0xab + i;
62 }
63
64 int iexpected = 20;
65 ARRAY_FOR_EACH(ai, entry) {
66 ck_assert_int_eq(*entry, iexpected);
67 ++iexpected;
68 }
69 ck_assert_int_eq(iexpected, 26);
70
71 int cexpected = 100;
72 ARRAY_FOR_EACH(ac, entry) {
73 ck_assert_int_eq(*entry, cexpected);
74 ++cexpected;
75 }
76 ck_assert_int_eq(cexpected, 110);
77
78 struct as sexpected = {
79 .a = 10,
80 .b = 20,
81 .ptr = (int*)0xab,
82 };
83 ARRAY_FOR_EACH(as, entry) {
84 ck_assert_int_eq(entry->a, sexpected.a);
85 ck_assert_int_eq(entry->b, sexpected.b);
86 ck_assert_ptr_eq(entry->ptr, sexpected.ptr);
87 ++sexpected.a;
88 ++sexpected.b;
89 ++sexpected.ptr;
90 }
91 ck_assert_int_eq(sexpected.a, 42);
92 }
93 END_TEST
94
START_TESTnull95 START_TEST(bitfield_helpers)
96 {
97 /* This value has a bit set on all of the word boundaries we want to
98 * test: 0, 1, 7, 8, 31, 32, and 33
99 */
100 unsigned char read_bitfield[] = { 0x83, 0x1, 0x0, 0x80, 0x3 };
101 unsigned char write_bitfield[ARRAY_LENGTH(read_bitfield)] = {0};
102 size_t i;
103
104 /* Now check that the bitfield we wrote to came out to be the same as
105 * the bitfield we were writing from */
106 for (i = 0; i < ARRAY_LENGTH(read_bitfield) * 8; i++) {
107 switch (i) {
108 case 0:
109 case 1:
110 case 7:
111 case 8:
112 case 31:
113 case 32:
114 case 33:
115 ck_assert(bit_is_set(read_bitfield, i));
116 set_bit(write_bitfield, i);
117 break;
118 default:
119 ck_assert(!bit_is_set(read_bitfield, i));
120 clear_bit(write_bitfield, i);
121 break;
122 }
123 }
124
125 ck_assert_int_eq(memcmp(read_bitfield,
126 write_bitfield,
127 sizeof(read_bitfield)),
128 0);
129 }
130 END_TEST
131
START_TESTnull132 START_TEST(matrix_helpers)
133 {
134 struct matrix m1, m2, m3;
135 float f[6] = { 1, 2, 3, 4, 5, 6 };
136 int x, y;
137 int row, col;
138
139 matrix_init_identity(&m1);
140
141 for (row = 0; row < 3; row++) {
142 for (col = 0; col < 3; col++) {
143 ck_assert_int_eq(m1.val[row][col],
144 (row == col) ? 1 : 0);
145 }
146 }
147 ck_assert(matrix_is_identity(&m1));
148
149 matrix_from_farray6(&m2, f);
150 ck_assert_int_eq(m2.val[0][0], 1);
151 ck_assert_int_eq(m2.val[0][1], 2);
152 ck_assert_int_eq(m2.val[0][2], 3);
153 ck_assert_int_eq(m2.val[1][0], 4);
154 ck_assert_int_eq(m2.val[1][1], 5);
155 ck_assert_int_eq(m2.val[1][2], 6);
156 ck_assert_int_eq(m2.val[2][0], 0);
157 ck_assert_int_eq(m2.val[2][1], 0);
158 ck_assert_int_eq(m2.val[2][2], 1);
159
160 x = 100;
161 y = 5;
162 matrix_mult_vec(&m1, &x, &y);
163 ck_assert_int_eq(x, 100);
164 ck_assert_int_eq(y, 5);
165
166 matrix_mult(&m3, &m1, &m1);
167 ck_assert(matrix_is_identity(&m3));
168
169 matrix_init_scale(&m2, 2, 4);
170 ck_assert_int_eq(m2.val[0][0], 2);
171 ck_assert_int_eq(m2.val[0][1], 0);
172 ck_assert_int_eq(m2.val[0][2], 0);
173 ck_assert_int_eq(m2.val[1][0], 0);
174 ck_assert_int_eq(m2.val[1][1], 4);
175 ck_assert_int_eq(m2.val[1][2], 0);
176 ck_assert_int_eq(m2.val[2][0], 0);
177 ck_assert_int_eq(m2.val[2][1], 0);
178 ck_assert_int_eq(m2.val[2][2], 1);
179
180 matrix_mult_vec(&m2, &x, &y);
181 ck_assert_int_eq(x, 200);
182 ck_assert_int_eq(y, 20);
183
184 matrix_init_translate(&m2, 10, 100);
185 ck_assert_int_eq(m2.val[0][0], 1);
186 ck_assert_int_eq(m2.val[0][1], 0);
187 ck_assert_int_eq(m2.val[0][2], 10);
188 ck_assert_int_eq(m2.val[1][0], 0);
189 ck_assert_int_eq(m2.val[1][1], 1);
190 ck_assert_int_eq(m2.val[1][2], 100);
191 ck_assert_int_eq(m2.val[2][0], 0);
192 ck_assert_int_eq(m2.val[2][1], 0);
193 ck_assert_int_eq(m2.val[2][2], 1);
194
195 matrix_mult_vec(&m2, &x, &y);
196 ck_assert_int_eq(x, 210);
197 ck_assert_int_eq(y, 120);
198
199 matrix_to_farray6(&m2, f);
200 ck_assert_int_eq(f[0], 1);
201 ck_assert_int_eq(f[1], 0);
202 ck_assert_int_eq(f[2], 10);
203 ck_assert_int_eq(f[3], 0);
204 ck_assert_int_eq(f[4], 1);
205 ck_assert_int_eq(f[5], 100);
206 }
207 END_TEST
208
START_TESTnull209 START_TEST(ratelimit_helpers)
210 {
211 struct ratelimit rl;
212 unsigned int i, j;
213
214 /* 10 attempts every 1000ms */
215 ratelimit_init(&rl, ms2us(1000), 10);
216
217 for (j = 0; j < 3; ++j) {
218 /* a burst of 9 attempts must succeed */
219 for (i = 0; i < 9; ++i) {
220 ck_assert_int_eq(ratelimit_test(&rl),
221 RATELIMIT_PASS);
222 }
223
224 /* the 10th attempt reaches the threshold */
225 ck_assert_int_eq(ratelimit_test(&rl), RATELIMIT_THRESHOLD);
226
227 /* ..then further attempts must fail.. */
228 ck_assert_int_eq(ratelimit_test(&rl), RATELIMIT_EXCEEDED);
229
230 /* ..regardless of how often we try. */
231 for (i = 0; i < 100; ++i) {
232 ck_assert_int_eq(ratelimit_test(&rl),
233 RATELIMIT_EXCEEDED);
234 }
235
236 /* ..even after waiting 20ms */
237 msleep(100);
238 for (i = 0; i < 100; ++i) {
239 ck_assert_int_eq(ratelimit_test(&rl),
240 RATELIMIT_EXCEEDED);
241 }
242
243 /* but after 1000ms the counter is reset */
244 msleep(950); /* +50ms to account for time drifts */
245 }
246 }
247 END_TEST
248
249 struct parser_test {
250 char *tag;
251 int expected_value;
252 };
253
START_TESTnull254 START_TEST(dpi_parser)
255 {
256 struct parser_test tests[] = {
257 { "450 *1800 3200", 1800 },
258 { "*450 1800 3200", 450 },
259 { "450 1800 *3200", 3200 },
260 { "450 1800 3200", 3200 },
261 { "450 1800 failboat", 0 },
262 { "450 1800 *failboat", 0 },
263 { "0 450 1800 *3200", 0 },
264 { "450@37 1800@12 *3200@6", 3200 },
265 { "450@125 1800@125 *3200@125 ", 3200 },
266 { "450@125 *1800@125 3200@125", 1800 },
267 { "*this @string fails", 0 },
268 { "12@34 *45@", 0 },
269 { "12@a *45@", 0 },
270 { "12@a *45@25", 0 },
271 { " * 12, 450, 800", 0 },
272 { " *12, 450, 800", 12 },
273 { "*12, *450, 800", 12 },
274 { "*-23412, 450, 800", 0 },
275 { "112@125, 450@125, 800@125, 900@-125", 0 },
276 { "", 0 },
277 { " ", 0 },
278 { "* ", 0 },
279 { NULL, 0 }
280 };
281 int i, dpi;
282
283 for (i = 0; tests[i].tag != NULL; i++) {
284 dpi = parse_mouse_dpi_property(tests[i].tag);
285 ck_assert_int_eq(dpi, tests[i].expected_value);
286 }
287
288 dpi = parse_mouse_dpi_property(NULL);
289 ck_assert_int_eq(dpi, 0);
290 }
291 END_TEST
292
START_TESTnull293 START_TEST(wheel_click_parser)
294 {
295 struct parser_test tests[] = {
296 { "1", 1 },
297 { "10", 10 },
298 { "-12", -12 },
299 { "360", 360 },
300
301 { "0", 0 },
302 { "-0", 0 },
303 { "a", 0 },
304 { "10a", 0 },
305 { "10-", 0 },
306 { "sadfasfd", 0 },
307 { "361", 0 },
308 { NULL, 0 }
309 };
310
311 int i, angle;
312
313 for (i = 0; tests[i].tag != NULL; i++) {
314 angle = parse_mouse_wheel_click_angle_property(tests[i].tag);
315 ck_assert_int_eq(angle, tests[i].expected_value);
316 }
317 }
318 END_TEST
319
START_TESTnull320 START_TEST(wheel_click_count_parser)
321 {
322 struct parser_test tests[] = {
323 { "1", 1 },
324 { "10", 10 },
325 { "-12", -12 },
326 { "360", 360 },
327
328 { "0", 0 },
329 { "-0", 0 },
330 { "a", 0 },
331 { "10a", 0 },
332 { "10-", 0 },
333 { "sadfasfd", 0 },
334 { "361", 0 },
335 { NULL, 0 }
336 };
337
338 int i, angle;
339
340 for (i = 0; tests[i].tag != NULL; i++) {
341 angle = parse_mouse_wheel_click_count_property(tests[i].tag);
342 ck_assert_int_eq(angle, tests[i].expected_value);
343 }
344
345 angle = parse_mouse_wheel_click_count_property(NULL);
346 ck_assert_int_eq(angle, 0);
347 }
348 END_TEST
349
START_TESTnull350 START_TEST(dimension_prop_parser)
351 {
352 struct parser_test_dimension {
353 char *tag;
354 bool success;
355 int x, y;
356 } tests[] = {
357 { "10x10", true, 10, 10 },
358 { "1x20", true, 1, 20 },
359 { "1x8000", true, 1, 8000 },
360 { "238492x428210", true, 238492, 428210 },
361 { "0x0", false, 0, 0 },
362 { "-10x10", false, 0, 0 },
363 { "-1", false, 0, 0 },
364 { "1x-99", false, 0, 0 },
365 { "0", false, 0, 0 },
366 { "100", false, 0, 0 },
367 { "", false, 0, 0 },
368 { "abd", false, 0, 0 },
369 { "xabd", false, 0, 0 },
370 { "0xaf", false, 0, 0 },
371 { "0x0x", false, 0, 0 },
372 { "x10", false, 0, 0 },
373 { NULL, false, 0, 0 }
374 };
375 int i;
376 size_t x, y;
377 bool success;
378
379 for (i = 0; tests[i].tag != NULL; i++) {
380 x = y = 0xad;
381 success = parse_dimension_property(tests[i].tag, &x, &y);
382 ck_assert(success == tests[i].success);
383 if (success) {
384 ck_assert_int_eq(x, tests[i].x);
385 ck_assert_int_eq(y, tests[i].y);
386 } else {
387 ck_assert_int_eq(x, 0xad);
388 ck_assert_int_eq(y, 0xad);
389 }
390 }
391
392 success = parse_dimension_property(NULL, &x, &y);
393 ck_assert(success == false);
394 }
395 END_TEST
396
START_TESTnull397 START_TEST(reliability_prop_parser)
398 {
399 struct parser_test_reliability {
400 char *tag;
401 bool success;
402 enum switch_reliability reliability;
403 } tests[] = {
404 { "reliable", true, RELIABILITY_RELIABLE },
405 { "unreliable", true, RELIABILITY_UNRELIABLE },
406 { "write_open", true, RELIABILITY_WRITE_OPEN },
407 { "", false, 0 },
408 { "0", false, 0 },
409 { "1", false, 0 },
410 { NULL, false, 0, }
411 };
412 enum switch_reliability r;
413 bool success;
414 int i;
415
416 for (i = 0; tests[i].tag != NULL; i++) {
417 r = 0xaf;
418 success = parse_switch_reliability_property(tests[i].tag, &r);
419 ck_assert(success == tests[i].success);
420 if (success)
421 ck_assert_int_eq(r, tests[i].reliability);
422 else
423 ck_assert_int_eq(r, 0xaf);
424 }
425
426 success = parse_switch_reliability_property(NULL, &r);
427 ck_assert(success == true);
428 ck_assert_int_eq(r, RELIABILITY_RELIABLE);
429
430 success = parse_switch_reliability_property("foo", NULL);
431 ck_assert(success == false);
432 }
433 END_TEST
434
START_TESTnull435 START_TEST(calibration_prop_parser)
436 {
437 #define DEFAULT_VALUES { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 }
438 const float untouched[6] = DEFAULT_VALUES;
439 struct parser_test_calibration {
440 char *prop;
441 bool success;
442 float values[6];
443 } tests[] = {
444 { "", false, DEFAULT_VALUES },
445 { "banana", false, DEFAULT_VALUES },
446 { "1 2 3 a 5 6", false, DEFAULT_VALUES },
447 { "2", false, DEFAULT_VALUES },
448 { "2 3 4 5 6", false, DEFAULT_VALUES },
449 { "1 2 3 4 5 6", true, DEFAULT_VALUES },
450 { "6.00012 3.244 4.238 5.2421 6.0134 8.860", true,
451 { 6.00012, 3.244, 4.238, 5.2421, 6.0134, 8.860 }},
452 { "0xff 2 3 4 5 6", false, DEFAULT_VALUES },
453 { NULL, false, DEFAULT_VALUES }
454 };
455 bool success;
456 float calibration[6];
457 int rc;
458 int i;
459
460 for (i = 0; tests[i].prop != NULL; i++) {
461 memcpy(calibration, untouched, sizeof(calibration));
462
463 success = parse_calibration_property(tests[i].prop,
464 calibration);
465 ck_assert_int_eq(success, tests[i].success);
466 if (success)
467 rc = memcmp(tests[i].values,
468 calibration,
469 sizeof(calibration));
470 else
471 rc = memcmp(untouched,
472 calibration,
473 sizeof(calibration));
474 ck_assert_int_eq(rc, 0);
475 }
476
477 memcpy(calibration, untouched, sizeof(calibration));
478
479 success = parse_calibration_property(NULL, calibration);
480 ck_assert(success == false);
481 rc = memcmp(untouched, calibration, sizeof(calibration));
482 ck_assert_int_eq(rc, 0);
483 }
484 END_TEST
485
START_TESTnull486 START_TEST(range_prop_parser)
487 {
488 struct parser_test_range {
489 char *tag;
490 bool success;
491 int hi, lo;
492 } tests[] = {
493 { "10:8", true, 10, 8 },
494 { "100:-1", true, 100, -1 },
495 { "-203813:-502023", true, -203813, -502023 },
496 { "238492:28210", true, 238492, 28210 },
497 { "none", true, 0, 0 },
498 { "0:0", false, 0, 0 },
499 { "", false, 0, 0 },
500 { "abcd", false, 0, 0 },
501 { "10:30:10", false, 0, 0 },
502 { NULL, false, 0, 0 }
503 };
504 int i;
505 int hi, lo;
506 bool success;
507
508 for (i = 0; tests[i].tag != NULL; i++) {
509 hi = lo = 0xad;
510 success = parse_range_property(tests[i].tag, &hi, &lo);
511 ck_assert(success == tests[i].success);
512 if (success) {
513 ck_assert_int_eq(hi, tests[i].hi);
514 ck_assert_int_eq(lo, tests[i].lo);
515 } else {
516 ck_assert_int_eq(hi, 0xad);
517 ck_assert_int_eq(lo, 0xad);
518 }
519 }
520
521 success = parse_range_property(NULL, NULL, NULL);
522 ck_assert(success == false);
523 }
524 END_TEST
525
START_TESTnull526 START_TEST(boolean_prop_parser)
527 {
528 struct parser_test_range {
529 char *tag;
530 bool success;
531 bool b;
532 } tests[] = {
533 { "0", true, false },
534 { "1", true, true },
535 { "-1", false, false },
536 { "2", false, false },
537 { "abcd", false, false },
538 { NULL, false, false }
539 };
540 int i;
541 bool success, b;
542
543 for (i = 0; tests[i].tag != NULL; i++) {
544 b = false;
545 success = parse_boolean_property(tests[i].tag, &b);
546 ck_assert(success == tests[i].success);
547 if (success)
548 ck_assert_int_eq(b, tests[i].b);
549 else
550 ck_assert_int_eq(b, false);
551 }
552
553 success = parse_boolean_property(NULL, NULL);
554 ck_assert(success == false);
555 }
556 END_TEST
557
START_TESTnull558 START_TEST(evcode_prop_parser)
559 {
560 struct parser_test_tuple {
561 const char *prop;
562 bool success;
563 size_t nevents;
564 struct input_event events[20];
565 } tests[] = {
566 { "+EV_KEY", true, 1, {{ .type = EV_KEY, .code = 0xffff, .value = 1 }} },
567 { "-EV_ABS;", true, 1, {{ .type = EV_ABS, .code = 0xffff, .value = 0 }} },
568 { "+ABS_X;", true, 1, {{ .type = EV_ABS, .code = ABS_X, .value = 1 }} },
569 { "-SW_TABLET_MODE;", true, 1, {{ .type = EV_SW, .code = SW_TABLET_MODE, .value = 0 }} },
570 { "+EV_SW", true, 1, {{ .type = EV_SW, .code = 0xffff, .value = 1 }} },
571 { "-ABS_Y", true, 1, {{ .type = EV_ABS, .code = ABS_Y, .value = 0 }} },
572 { "+EV_ABS:0x00", true, 1, {{ .type = EV_ABS, .code = ABS_X, .value = 1 }} },
573 { "-EV_ABS:01", true, 1, {{ .type = EV_ABS, .code = ABS_Y, .value = 0 }} },
574 { "+ABS_TILT_X;-ABS_TILT_Y;", true, 2,
575 {{ .type = EV_ABS, .code = ABS_TILT_X, .value = 1 },
576 { .type = EV_ABS, .code = ABS_TILT_Y, .value = 0}} },
577 { "+BTN_TOOL_DOUBLETAP;+EV_KEY;-KEY_A", true, 3,
578 {{ .type = EV_KEY, .code = BTN_TOOL_DOUBLETAP, .value = 1 } ,
579 { .type = EV_KEY, .code = 0xffff, .value = 1 },
580 { .type = EV_KEY, .code = KEY_A, .value = 0 }} },
581 { "+REL_Y;-ABS_Z;+BTN_STYLUS", true, 3,
582 {{ .type = EV_REL, .code = REL_Y, .value = 1},
583 { .type = EV_ABS, .code = ABS_Z, .value = 0},
584 { .type = EV_KEY, .code = BTN_STYLUS, .value = 1 }} },
585 { "-REL_Y;+EV_KEY:0x123;-BTN_STYLUS", true, 3,
586 {{ .type = EV_REL, .code = REL_Y, .value = 0 },
587 { .type = EV_KEY, .code = 0x123, .value = 1 },
588 { .type = EV_KEY, .code = BTN_STYLUS, .value = 0 }} },
589 { .prop = "", .success = false },
590 { .prop = "+", .success = false },
591 { .prop = "-", .success = false },
592 { .prop = "!", .success = false },
593 { .prop = "+EV_FOO", .success = false },
594 { .prop = "+EV_KEY;-EV_FOO", .success = false },
595 { .prop = "+BTN_STYLUS;-EV_FOO", .success = false },
596 { .prop = "-BTN_UNKNOWN", .success = false },
597 { .prop = "+BTN_UNKNOWN;+EV_KEY", .success = false },
598 { .prop = "-PR_UNKNOWN", .success = false },
599 { .prop = "-BTN_STYLUS;+PR_UNKNOWN;-ABS_X", .success = false },
600 { .prop = "-EV_REL:0xffff", .success = false },
601 { .prop = "-EV_REL:0x123.", .success = false },
602 { .prop = "-EV_REL:ffff", .success = false },
603 { .prop = "-EV_REL:blah", .success = false },
604 { .prop = "+KEY_A:0x11", .success = false },
605 { .prop = "+EV_KEY:0x11 ", .success = false },
606 { .prop = "+EV_KEY:0x11not", .success = false },
607 { .prop = "none", .success = false },
608 { .prop = NULL },
609 };
610 struct parser_test_tuple *t;
611
612 for (int i = 0; tests[i].prop; i++) {
613 bool success;
614 struct input_event events[32];
615 size_t nevents = ARRAY_LENGTH(events);
616
617 t = &tests[i];
618 success = parse_evcode_property(t->prop, events, &nevents);
619 ck_assert(success == t->success);
620 if (!success)
621 continue;
622
623 ck_assert_int_eq(nevents, t->nevents);
624 for (size_t j = 0; j < nevents; j++) {
625 unsigned int type = events[j].type;
626 unsigned int code = events[j].code;
627 int value = events[j].value;
628 ck_assert_int_eq(t->events[j].type, type);
629 ck_assert_int_eq(t->events[j].code, code);
630 ck_assert_int_eq(t->events[j].value, value);
631 }
632 }
633 }
634 END_TEST
635
START_TESTnull636 START_TEST(input_prop_parser)
637 {
638 struct parser_test_val {
639 const char *prop;
640 bool success;
641 size_t nvals;
642 struct input_prop values[20];
643 } tests[] = {
644 { "+INPUT_PROP_BUTTONPAD", true, 1, {{ INPUT_PROP_BUTTONPAD, true }}},
645 { "+INPUT_PROP_BUTTONPAD;-INPUT_PROP_POINTER", true, 2,
646 { { INPUT_PROP_BUTTONPAD, true },
647 { INPUT_PROP_POINTER, false }}},
648 { "+INPUT_PROP_BUTTONPAD;-0x00;+0x03", true, 3,
649 { { INPUT_PROP_BUTTONPAD, true },
650 { INPUT_PROP_POINTER, false },
651 { INPUT_PROP_SEMI_MT, true }}},
652 { .prop = "", .success = false },
653 { .prop = "0xff", .success = false },
654 { .prop = "INPUT_PROP", .success = false },
655 { .prop = "INPUT_PROP_FOO", .success = false },
656 { .prop = "INPUT_PROP_FOO;INPUT_PROP_FOO", .success = false },
657 { .prop = "INPUT_PROP_POINTER;INPUT_PROP_FOO", .success = false },
658 { .prop = "none", .success = false },
659 { .prop = NULL },
660 };
661 struct parser_test_val *t;
662
663 for (int i = 0; tests[i].prop; i++) {
664 bool success;
665 struct input_prop props[32];
666 size_t nprops = ARRAY_LENGTH(props);
667
668 t = &tests[i];
669 success = parse_input_prop_property(t->prop, props, &nprops);
670 ck_assert(success == t->success);
671 if (!success)
672 continue;
673
674 ck_assert_int_eq(nprops, t->nvals);
675 for (size_t j = 0; j < t->nvals; j++) {
676 ck_assert_int_eq(t->values[j].prop, props[j].prop);
677 ck_assert_int_eq(t->values[j].enabled, props[j].enabled);
678 }
679 }
680 }
681 END_TEST
682
START_TESTnull683 START_TEST(evdev_abs_parser)
684 {
685 struct test {
686 uint32_t which;
687 const char *prop;
688 int min, max, res, fuzz, flat;
689
690 } tests[] = {
691 { .which = (ABS_MASK_MIN|ABS_MASK_MAX),
692 .prop = "1:2",
693 .min = 1, .max = 2 },
694 { .which = (ABS_MASK_MIN|ABS_MASK_MAX),
695 .prop = "1:2:",
696 .min = 1, .max = 2 },
697 { .which = (ABS_MASK_MIN|ABS_MASK_MAX|ABS_MASK_RES),
698 .prop = "10:20:30",
699 .min = 10, .max = 20, .res = 30 },
700 { .which = (ABS_MASK_RES),
701 .prop = "::100",
702 .res = 100 },
703 { .which = (ABS_MASK_MIN),
704 .prop = "10:",
705 .min = 10 },
706 { .which = (ABS_MASK_MAX|ABS_MASK_RES),
707 .prop = ":10:1001",
708 .max = 10, .res = 1001 },
709 { .which = (ABS_MASK_MIN|ABS_MASK_MAX|ABS_MASK_RES|ABS_MASK_FUZZ),
710 .prop = "1:2:3:4",
711 .min = 1, .max = 2, .res = 3, .fuzz = 4},
712 { .which = (ABS_MASK_MIN|ABS_MASK_MAX|ABS_MASK_RES|ABS_MASK_FUZZ|ABS_MASK_FLAT),
713 .prop = "1:2:3:4:5",
714 .min = 1, .max = 2, .res = 3, .fuzz = 4, .flat = 5},
715 { .which = (ABS_MASK_MIN|ABS_MASK_RES|ABS_MASK_FUZZ|ABS_MASK_FLAT),
716 .prop = "1::3:4:50",
717 .min = 1, .res = 3, .fuzz = 4, .flat = 50},
718 { .which = ABS_MASK_FUZZ|ABS_MASK_FLAT,
719 .prop = ":::5:60",
720 .fuzz = 5, .flat = 60},
721 { .which = ABS_MASK_FUZZ,
722 .prop = ":::5:",
723 .fuzz = 5 },
724 { .which = ABS_MASK_RES, .prop = "::12::",
725 .res = 12 },
726 /* Malformed property but parsing this one makes us more
727 * future proof */
728 { .which = (ABS_MASK_RES|ABS_MASK_FUZZ|ABS_MASK_FLAT),
729 .prop = "::12:1:2:3:4:5:6",
730 .res = 12, .fuzz = 1, .flat = 2 },
731 { .which = 0, .prop = ":::::" },
732 { .which = 0, .prop = ":" },
733 { .which = 0, .prop = "" },
734 { .which = 0, .prop = ":asb::::" },
735 { .which = 0, .prop = "foo" },
736 };
737
738 ARRAY_FOR_EACH(tests, t) {
739 struct input_absinfo abs;
740 uint32_t mask;
741
742 mask = parse_evdev_abs_prop(t->prop, &abs);
743 ck_assert_int_eq(mask, t->which);
744
745 if (t->which & ABS_MASK_MIN)
746 ck_assert_int_eq(abs.minimum, t->min);
747 if (t->which & ABS_MASK_MAX)
748 ck_assert_int_eq(abs.maximum, t->max);
749 if (t->which & ABS_MASK_RES)
750 ck_assert_int_eq(abs.resolution, t->res);
751 if (t->which & ABS_MASK_FUZZ)
752 ck_assert_int_eq(abs.fuzz, t->fuzz);
753 if (t->which & ABS_MASK_FLAT)
754 ck_assert_int_eq(abs.flat, t->flat);
755 }
756 }
757 END_TEST
758
START_TESTnull759 START_TEST(time_conversion)
760 {
761 ck_assert_int_eq(us(10), 10);
762 ck_assert_int_eq(ns2us(10000), 10);
763 ck_assert_int_eq(ms2us(10), 10000);
764 ck_assert_int_eq(s2us(1), 1000000);
765 ck_assert_int_eq(h2us(2), s2us(2 * 60 * 60));
766 ck_assert_int_eq(us2ms(10000), 10);
767 }
768 END_TEST
769
START_TESTnull770 START_TEST(human_time)
771 {
772 struct ht_tests {
773 uint64_t interval;
774 unsigned int value;
775 const char *unit;
776 } tests[] = {
777 { 0, 0, "us" },
778 { 123, 123, "us" },
779 { ms2us(5), 5, "ms" },
780 { ms2us(100), 100, "ms" },
781 { s2us(5), 5, "s" },
782 { s2us(100), 100, "s" },
783 { s2us(120), 2, "min" },
784 { 5 * s2us(60), 5, "min" },
785 { 120 * s2us(60), 2, "h" },
786 { 5 * 60 * s2us(60), 5, "h" },
787 { 48 * 60 * s2us(60), 2, "d" },
788 { 1000 * 24 * 60 * s2us(60), 1000, "d" },
789 { 0, 0, NULL },
790 };
791 for (int i = 0; tests[i].unit != NULL; i++) {
792 struct human_time ht;
793
794 ht = to_human_time(tests[i].interval);
795 ck_assert_int_eq(ht.value, tests[i].value);
796 ck_assert_str_eq(ht.unit, tests[i].unit);
797 }
798 }
799 END_TEST
800
801 struct atoi_test {
802 char *str;
803 bool success;
804 int val;
805 };
806
START_TESTnull807 START_TEST(safe_atoi_test)
808 {
809 struct atoi_test tests[] = {
810 { "10", true, 10 },
811 { "20", true, 20 },
812 { "-1", true, -1 },
813 { "2147483647", true, 2147483647 },
814 { "-2147483648", true, -2147483648 },
815 { "4294967295", false, 0 },
816 { "0x0", false, 0 },
817 { "-10x10", false, 0 },
818 { "1x-99", false, 0 },
819 { "", false, 0 },
820 { "abd", false, 0 },
821 { "xabd", false, 0 },
822 { "0xaf", false, 0 },
823 { "0x0x", false, 0 },
824 { "x10", false, 0 },
825 { NULL, false, 0 }
826 };
827 int v;
828 bool success;
829
830 for (int i = 0; tests[i].str != NULL; i++) {
831 v = 0xad;
832 success = safe_atoi(tests[i].str, &v);
833 ck_assert(success == tests[i].success);
834 if (success)
835 ck_assert_int_eq(v, tests[i].val);
836 else
837 ck_assert_int_eq(v, 0xad);
838 }
839 }
840 END_TEST
841
START_TESTnull842 START_TEST(safe_atoi_base_16_test)
843 {
844 struct atoi_test tests[] = {
845 { "10", true, 0x10 },
846 { "20", true, 0x20 },
847 { "-1", true, -1 },
848 { "0x10", true, 0x10 },
849 { "0xff", true, 0xff },
850 { "abc", true, 0xabc },
851 { "-10", true, -0x10 },
852 { "0x0", true, 0 },
853 { "0", true, 0 },
854 { "0x-99", false, 0 },
855 { "0xak", false, 0 },
856 { "0x", false, 0 },
857 { "x10", false, 0 },
858 { NULL, false, 0 }
859 };
860
861 int v;
862 bool success;
863
864 for (int i = 0; tests[i].str != NULL; i++) {
865 v = 0xad;
866 success = safe_atoi_base(tests[i].str, &v, 16);
867 ck_assert(success == tests[i].success);
868 if (success)
869 ck_assert_int_eq(v, tests[i].val);
870 else
871 ck_assert_int_eq(v, 0xad);
872 }
873 }
874 END_TEST
875
START_TESTnull876 START_TEST(safe_atoi_base_8_test)
877 {
878 struct atoi_test tests[] = {
879 { "7", true, 07 },
880 { "10", true, 010 },
881 { "20", true, 020 },
882 { "-1", true, -1 },
883 { "010", true, 010 },
884 { "0ff", false, 0 },
885 { "abc", false, 0},
886 { "0xabc", false, 0},
887 { "-10", true, -010 },
888 { "0", true, 0 },
889 { "00", true, 0 },
890 { "0x0", false, 0 },
891 { "0x-99", false, 0 },
892 { "0xak", false, 0 },
893 { "0x", false, 0 },
894 { "x10", false, 0 },
895 { NULL, false, 0 }
896 };
897
898 int v;
899 bool success;
900
901 for (int i = 0; tests[i].str != NULL; i++) {
902 v = 0xad;
903 success = safe_atoi_base(tests[i].str, &v, 8);
904 ck_assert(success == tests[i].success);
905 if (success)
906 ck_assert_int_eq(v, tests[i].val);
907 else
908 ck_assert_int_eq(v, 0xad);
909 }
910 }
911 END_TEST
912
913 struct atou_test {
914 char *str;
915 bool success;
916 unsigned int val;
917 };
918
START_TESTnull919 START_TEST(safe_atou_test)
920 {
921 struct atou_test tests[] = {
922 { "10", true, 10 },
923 { "20", true, 20 },
924 { "-1", false, 0 },
925 { "2147483647", true, 2147483647 },
926 { "-2147483648", false, 0},
927 { "0x0", false, 0 },
928 { "-10x10", false, 0 },
929 { "1x-99", false, 0 },
930 { "", false, 0 },
931 { "abd", false, 0 },
932 { "xabd", false, 0 },
933 { "0xaf", false, 0 },
934 { "0x0x", false, 0 },
935 { "x10", false, 0 },
936 { NULL, false, 0 }
937 };
938 unsigned int v;
939 bool success;
940
941 for (int i = 0; tests[i].str != NULL; i++) {
942 v = 0xad;
943 success = safe_atou(tests[i].str, &v);
944 ck_assert(success == tests[i].success);
945 if (success)
946 ck_assert_int_eq(v, tests[i].val);
947 else
948 ck_assert_int_eq(v, 0xad);
949 }
950 }
951 END_TEST
952
START_TESTnull953 START_TEST(safe_atou_base_16_test)
954 {
955 struct atou_test tests[] = {
956 { "10", true, 0x10 },
957 { "20", true, 0x20 },
958 { "-1", false, 0 },
959 { "0x10", true, 0x10 },
960 { "0xff", true, 0xff },
961 { "abc", true, 0xabc },
962 { "-10", false, 0 },
963 { "0x0", true, 0 },
964 { "0", true, 0 },
965 { "0x-99", false, 0 },
966 { "0xak", false, 0 },
967 { "0x", false, 0 },
968 { "x10", false, 0 },
969 { NULL, false, 0 }
970 };
971
972 unsigned int v;
973 bool success;
974
975 for (int i = 0; tests[i].str != NULL; i++) {
976 v = 0xad;
977 success = safe_atou_base(tests[i].str, &v, 16);
978 ck_assert(success == tests[i].success);
979 if (success)
980 ck_assert_int_eq(v, tests[i].val);
981 else
982 ck_assert_int_eq(v, 0xad);
983 }
984 }
985 END_TEST
986
START_TESTnull987 START_TEST(safe_atou_base_8_test)
988 {
989 struct atou_test tests[] = {
990 { "7", true, 07 },
991 { "10", true, 010 },
992 { "20", true, 020 },
993 { "-1", false, 0 },
994 { "010", true, 010 },
995 { "0ff", false, 0 },
996 { "abc", false, 0},
997 { "0xabc", false, 0},
998 { "-10", false, 0 },
999 { "0", true, 0 },
1000 { "00", true, 0 },
1001 { "0x0", false, 0 },
1002 { "0x-99", false, 0 },
1003 { "0xak", false, 0 },
1004 { "0x", false, 0 },
1005 { "x10", false, 0 },
1006 { NULL, false, 0 }
1007 };
1008
1009 unsigned int v;
1010 bool success;
1011
1012 for (int i = 0; tests[i].str != NULL; i++) {
1013 v = 0xad;
1014 success = safe_atou_base(tests[i].str, &v, 8);
1015 ck_assert(success == tests[i].success);
1016 if (success)
1017 ck_assert_int_eq(v, tests[i].val);
1018 else
1019 ck_assert_int_eq(v, 0xad);
1020 }
1021 }
1022 END_TEST
1023
START_TESTnull1024 START_TEST(safe_atod_test)
1025 {
1026 struct atod_test {
1027 char *str;
1028 bool success;
1029 double val;
1030 } tests[] = {
1031 { "10", true, 10 },
1032 { "20", true, 20 },
1033 { "-1", true, -1 },
1034 { "2147483647", true, 2147483647 },
1035 { "-2147483648", true, -2147483648 },
1036 { "4294967295", true, 4294967295 },
1037 { "0x0", false, 0 },
1038 { "0x10", false, 0 },
1039 { "0xaf", false, 0 },
1040 { "x80", false, 0 },
1041 { "0.0", true, 0.0 },
1042 { "0.1", true, 0.1 },
1043 { "1.2", true, 1.2 },
1044 { "-324.9", true, -324.9 },
1045 { "9324.9", true, 9324.9 },
1046 { "NAN", false, 0 },
1047 { "INFINITY", false, 0 },
1048 { "-10x10", false, 0 },
1049 { "1x-99", false, 0 },
1050 { "", false, 0 },
1051 { "abd", false, 0 },
1052 { "xabd", false, 0 },
1053 { "0x0x", false, 0 },
1054 { NULL, false, 0 }
1055 };
1056 double v;
1057 bool success;
1058
1059 for (int i = 0; tests[i].str != NULL; i++) {
1060 v = 0xad;
1061 success = safe_atod(tests[i].str, &v);
1062 ck_assert(success == tests[i].success);
1063 if (success)
1064 ck_assert_int_eq(v, tests[i].val);
1065 else
1066 ck_assert_int_eq(v, 0xad);
1067 }
1068 }
1069 END_TEST
1070
START_TESTnull1071 START_TEST(strsplit_test)
1072 {
1073 struct strsplit_test {
1074 const char *string;
1075 const char *delim;
1076 const char *results[10];
1077 const size_t nresults;
1078 } tests[] = {
1079 { "one two three", " ", { "one", "two", "three", NULL }, 3 },
1080 { "one two\tthree", " \t", { "one", "two", "three", NULL }, 3 },
1081 { "one", " ", { "one", NULL }, 1 },
1082 { "one two ", " ", { "one", "two", NULL }, 2 },
1083 { "one two", " ", { "one", "two", NULL }, 2 },
1084 { " one two", " ", { "one", "two", NULL }, 2 },
1085 { "one", "\t \r", { "one", NULL }, 1 },
1086 { "one two three", " t", { "one", "wo", "hree", NULL }, 3 },
1087 { " one two three", "te", { " on", " ", "wo ", "hr", NULL }, 4 },
1088 { "one", "ne", { "o", NULL }, 1 },
1089 { "onene", "ne", { "o", NULL }, 1 },
1090 { "+1-2++3--4++-+5-+-", "+-", { "1", "2", "3", "4", "5", NULL }, 5 },
1091 /* special cases */
1092 { "", " ", { NULL }, 0 },
1093 { " ", " ", { NULL }, 0 },
1094 { " ", " ", { NULL }, 0 },
1095 { "oneoneone", "one", { NULL} , 0 },
1096 { NULL, NULL, { NULL }, 0}
1097 };
1098 struct strsplit_test *t = tests;
1099
1100 while (t->string) {
1101 size_t nelem;
1102 char **strv = strv_from_string(t->string, t->delim, &nelem);
1103
1104 for (size_t idx = 0; idx < t->nresults; idx++)
1105 ck_assert_str_eq(t->results[idx], strv[idx]);
1106
1107 ck_assert_uint_eq(nelem, t->nresults);
1108
1109 /* When there are no elements validate return value is Null,
1110 otherwise validate result array is Null terminated. */
1111 if(t->nresults == 0)
1112 ck_assert_ptr_eq(strv, NULL);
1113 else
1114 ck_assert_ptr_eq(strv[t->nresults], NULL);
1115
1116 strv_free(strv);
1117 t++;
1118 }
1119 }
1120 END_TEST
1121
START_TESTnull1122 START_TEST(double_array_from_string_test)
1123 {
1124 struct double_array_from_string_test {
1125 const char *string;
1126 const char *delim;
1127 const double array[10];
1128 const size_t len;
1129 const bool result;
1130 } tests[] = {
1131 { "1 2 3", " ", { 1, 2, 3 }, 3 },
1132 { "1", " ", { 1 }, 1 },
1133 { "1,2.5,", ",", { 1, 2.5 }, 2 },
1134 { "1.0 2", " ", { 1, 2.0 }, 2 },
1135 { " 1 2", " ", { 1, 2 }, 2 },
1136 { " ; 1;2 3.5 ;;4.1", "; ", { 1, 2, 3.5, 4.1 }, 4 },
1137 /* special cases */
1138 { "1 two", " ", { 0 }, 0 },
1139 { "one two", " ", { 0 }, 0 },
1140 { "one 2", " ", { 0 }, 0 },
1141 { "", " ", { 0 }, 0 },
1142 { " ", " ", { 0 }, 0 },
1143 { " ", " ", { 0 }, 0 },
1144 { "", " ", { 0 }, 0 },
1145 { "oneoneone", "one", { 0 }, 0 },
1146 { NULL, NULL, { 0 }, 0 }
1147 };
1148 struct double_array_from_string_test *t = tests;
1149
1150 while (t->string) {
1151 size_t len;
1152 double *array = double_array_from_string(t->string,
1153 t->delim,
1154 &len);
1155 ck_assert_int_eq(len, t->len);
1156
1157 for (size_t idx = 0; idx < len; idx++)
1158 ck_assert_double_eq(array[idx], t->array[idx]);
1159
1160 free(array);
1161 t++;
1162 }
1163 }
1164 END_TEST
1165
START_TESTnull1166 START_TEST(strargv_test)
1167 {
1168 struct argv_test {
1169 int argc;
1170 char *argv[10];
1171 int expected;
1172 } tests[] = {
1173 { 0, {NULL}, 0 },
1174 { 1, {"hello", "World"}, 1 },
1175 { 2, {"hello", "World"}, 2 },
1176 { 2, {"", " "}, 2 },
1177 { 2, {"", NULL}, 0 },
1178 { 2, {NULL, NULL}, 0 },
1179 { 1, {NULL, NULL}, 0 },
1180 { 3, {"hello", NULL, "World"}, 0 },
1181 };
1182
1183 ARRAY_FOR_EACH(tests, t) {
1184 char **strv = strv_from_argv(t->argc, t->argv);
1185
1186 if (t->expected == 0) {
1187 ck_assert(strv == NULL);
1188 } else {
1189 int count = 0;
1190 char **s = strv;
1191 while (*s) {
1192 ck_assert_str_eq(*s, t->argv[count]);
1193 count++;
1194 s++;
1195 }
1196 ck_assert_int_eq(t->expected, count);
1197 strv_free(strv);
1198 }
1199 }
1200 }
1201 END_TEST
1202
START_TESTnull1203 START_TEST(kvsplit_double_test)
1204 {
1205 struct kvsplit_dbl_test {
1206 const char *string;
1207 const char *psep;
1208 const char *kvsep;
1209 ssize_t nresults;
1210 struct {
1211 double a;
1212 double b;
1213 } results[32];
1214 } tests[] = {
1215 { "1:2;3:4;5:6", ";", ":", 3, { {1, 2}, {3, 4}, {5, 6}}},
1216 { "1.0x2.3 -3.2x4.5 8.090909x-6.00", " ", "x", 3, { {1.0, 2.3}, {-3.2, 4.5}, {8.090909, -6}}},
1217
1218 { "1:2", "x", ":", 1, {{1, 2}}},
1219 { "1:2", ":", "x", -1, {}},
1220 { "1:2", NULL, "x", -1, {}},
1221 { "1:2", "", "x", -1, {}},
1222 { "1:2", "x", NULL, -1, {}},
1223 { "1:2", "x", "", -1, {}},
1224 { "a:b", "x", ":", -1, {}},
1225 { "", " ", "x", -1, {}},
1226 { "1.2.3.4.5", ".", "", -1, {}},
1227 { NULL }
1228 };
1229 struct kvsplit_dbl_test *t = tests;
1230
1231 while (t->string) {
1232 struct key_value_double *result = NULL;
1233 ssize_t npairs;
1234
1235 npairs = kv_double_from_string(t->string,
1236 t->psep,
1237 t->kvsep,
1238 &result);
1239 ck_assert_int_eq(npairs, t->nresults);
1240
1241 for (ssize_t i = 0; i < npairs; i++) {
1242 ck_assert_double_eq(t->results[i].a, result[i].key);
1243 ck_assert_double_eq(t->results[i].b, result[i].value);
1244 }
1245
1246
1247 free(result);
1248 t++;
1249 }
1250 }
1251 END_TEST
1252
START_TESTnull1253 START_TEST(strjoin_test)
1254 {
1255 struct strjoin_test {
1256 char *strv[10];
1257 const char *joiner;
1258 const char *result;
1259 } tests[] = {
1260 { { "one", "two", "three", NULL }, " ", "one two three" },
1261 { { "one", NULL }, "x", "one" },
1262 { { "one", "two", NULL }, "x", "onextwo" },
1263 { { "one", "two", NULL }, ",", "one,two" },
1264 { { "one", "two", NULL }, ", ", "one, two" },
1265 { { "one", "two", NULL }, "one", "oneonetwo" },
1266 { { "one", "two", NULL }, NULL, NULL },
1267 { { "", "", "", NULL }, " ", " " },
1268 { { "a", "b", "c", NULL }, "", "abc" },
1269 { { "", "b", "c", NULL }, "x", "xbxc" },
1270 { { "", "", "", NULL }, "", "" },
1271 { { NULL }, NULL, NULL }
1272 };
1273 struct strjoin_test *t = tests;
1274 struct strjoin_test nulltest = { {NULL}, "x", NULL };
1275
1276 while (t->strv[0]) {
1277 char *str;
1278 str = strv_join(t->strv, t->joiner);
1279 if (t->result == NULL)
1280 ck_assert(str == NULL);
1281 else
1282 ck_assert_str_eq(str, t->result);
1283 free(str);
1284 t++;
1285 }
1286
1287 ck_assert(strv_join(nulltest.strv, "x") == NULL);
1288 }
1289 END_TEST
1290
START_TESTnull1291 START_TEST(strstrip_test)
1292 {
1293 struct strstrip_test {
1294 const char *string;
1295 const char *expected;
1296 const char *what;
1297 } tests[] = {
1298 { "foo", "foo", "1234" },
1299 { "\"bar\"", "bar", "\"" },
1300 { "'bar'", "bar", "'" },
1301 { "\"bar\"", "\"bar\"", "'" },
1302 { "'bar'", "'bar'", "\"" },
1303 { "\"bar\"", "bar", "\"" },
1304 { "\"\"", "", "\"" },
1305 { "\"foo\"bar\"", "foo\"bar", "\"" },
1306 { "\"'foo\"bar\"", "foo\"bar", "\"'" },
1307 { "abcfooabcbarbca", "fooabcbar", "abc" },
1308 { "xxxxfoo", "foo", "x" },
1309 { "fooyyyy", "foo", "y" },
1310 { "xxxxfooyyyy", "foo", "xy" },
1311 { "x xfooy y", " xfooy ", "xy" },
1312 { " foo\n", "foo", " \n" },
1313 { "", "", "abc" },
1314 { "", "", "" },
1315 { NULL , NULL, NULL }
1316 };
1317 struct strstrip_test *t = tests;
1318
1319 while (t->string) {
1320 char *str;
1321 str = strstrip(t->string, t->what);
1322 ck_assert_str_eq(str, t->expected);
1323 free(str);
1324 t++;
1325 }
1326 }
1327 END_TEST
1328
START_TESTnull1329 START_TEST(strendswith_test)
1330 {
1331 struct strendswith_test {
1332 const char *string;
1333 const char *suffix;
1334 bool expected;
1335 } tests[] = {
1336 { "foobar", "bar", true },
1337 { "foobar", "foo", false },
1338 { "foobar", "foobar", true },
1339 { "foo", "foobar", false },
1340 { "foobar", "", false },
1341 { "", "", false },
1342 { "", "foo", false },
1343 { NULL, NULL, false },
1344 };
1345
1346 for (struct strendswith_test *t = tests; t->string; t++) {
1347 ck_assert_int_eq(strendswith(t->string, t->suffix),
1348 t->expected);
1349 }
1350 }
1351 END_TEST
1352
START_TESTnull1353 START_TEST(strstartswith_test)
1354 {
1355 struct strstartswith_test {
1356 const char *string;
1357 const char *suffix;
1358 bool expected;
1359 } tests[] = {
1360 { "foobar", "foo", true },
1361 { "foobar", "bar", false },
1362 { "foobar", "foobar", true },
1363 { "foo", "foobar", false },
1364 { "foo", "", false },
1365 { "", "", false },
1366 { "foo", "", false },
1367 { NULL, NULL, false },
1368 };
1369
1370 for (struct strstartswith_test *t = tests; t->string; t++) {
1371 ck_assert_int_eq(strstartswith(t->string, t->suffix),
1372 t->expected);
1373 }
1374 }
1375 END_TEST
1376
START_TESTnull1377 START_TEST(strsanitize_test)
1378 {
1379 struct strsanitize_test {
1380 const char *string;
1381 const char *expected;
1382 } tests[] = {
1383 { "foobar", "foobar" },
1384 { "", "" },
1385 { "%", "%%" },
1386 { "%%%%", "%%%%%%%%" },
1387 { "x %s", "x %%s" },
1388 { "x %", "x %%" },
1389 { "%sx", "%%sx" },
1390 { "%s%s", "%%s%%s" },
1391 { NULL, NULL },
1392 };
1393
1394 for (struct strsanitize_test *t = tests; t->string; t++) {
1395 char *sanitized = str_sanitize(t->string);
1396 ck_assert_str_eq(sanitized, t->expected);
1397 free(sanitized);
1398 }
1399 }
1400 END_TEST
1401
START_TESTnull1402 START_TEST(list_test_insert)
1403 {
1404 struct list_test {
1405 int val;
1406 struct list node;
1407 } tests[] = {
1408 { .val = 1 },
1409 { .val = 2 },
1410 { .val = 3 },
1411 { .val = 4 },
1412 };
1413 struct list_test *t;
1414 struct list head;
1415 int val;
1416
1417 list_init(&head);
1418
1419 ARRAY_FOR_EACH(tests, t) {
1420 list_insert(&head, &t->node);
1421 }
1422
1423 val = 4;
1424 list_for_each(t, &head, node) {
1425 ck_assert_int_eq(t->val, val);
1426 val--;
1427 }
1428
1429 ck_assert_int_eq(val, 0);
1430 }
1431 END_TEST
1432
START_TESTnull1433 START_TEST(list_test_append)
1434 {
1435 struct list_test {
1436 int val;
1437 struct list node;
1438 } tests[] = {
1439 { .val = 1 },
1440 { .val = 2 },
1441 { .val = 3 },
1442 { .val = 4 },
1443 };
1444 struct list_test *t;
1445 struct list head;
1446 int val;
1447
1448 list_init(&head);
1449
1450 ARRAY_FOR_EACH(tests, t) {
1451 list_append(&head, &t->node);
1452 }
1453
1454 val = 1;
1455 list_for_each(t, &head, node) {
1456 ck_assert_int_eq(t->val, val);
1457 val++;
1458 }
1459 ck_assert_int_eq(val, 5);
1460 }
1461 END_TEST
1462
START_TESTnull1463 START_TEST(list_test_foreach)
1464 {
1465 struct list_test {
1466 int val;
1467 struct list node;
1468 } tests[] = {
1469 { .val = 1 },
1470 { .val = 2 },
1471 { .val = 3 },
1472 { .val = 4 },
1473 };
1474 struct list_test *t;
1475 struct list head;
1476
1477 list_init(&head);
1478
1479 ARRAY_FOR_EACH(tests, t) {
1480 list_append(&head, &t->node);
1481 }
1482
1483 /* Make sure both loop macros are a single line statement */
1484 if (false)
1485 list_for_each(t, &head, node) {
1486 ck_abort_msg("We should not get here");
1487 }
1488
1489 if (false)
1490 list_for_each_safe(t, &head, node) {
1491 ck_abort_msg("We should not get here");
1492 }
1493 }
1494 END_TEST
1495
START_TESTnull1496 START_TEST(strverscmp_test)
1497 {
1498 ck_assert_int_eq(libinput_strverscmp("", ""), 0);
1499 ck_assert_int_gt(libinput_strverscmp("0.0.1", ""), 0);
1500 ck_assert_int_lt(libinput_strverscmp("", "0.0.1"), 0);
1501 ck_assert_int_eq(libinput_strverscmp("0.0.1", "0.0.1"), 0);
1502 ck_assert_int_eq(libinput_strverscmp("0.0.1", "0.0.2"), -1);
1503 ck_assert_int_eq(libinput_strverscmp("0.0.2", "0.0.1"), 1);
1504 ck_assert_int_eq(libinput_strverscmp("0.0.1", "0.1.0"), -1);
1505 ck_assert_int_eq(libinput_strverscmp("0.1.0", "0.0.1"), 1);
1506 }
1507 END_TEST
1508
START_TESTnull1509 START_TEST(streq_test)
1510 {
1511 ck_assert(streq("", "") == true);
1512 ck_assert(streq(NULL, NULL) == true);
1513 ck_assert(streq("0.0.1", "") == false);
1514 ck_assert(streq("foo", NULL) == false);
1515 ck_assert(streq(NULL, "foo") == false);
1516 ck_assert(streq("0.0.1", "0.0.1") == true);
1517 }
1518 END_TEST
1519
START_TESTnull1520 START_TEST(strneq_test)
1521 {
1522 ck_assert(strneq("", "", 1) == true);
1523 ck_assert(strneq(NULL, NULL, 1) == true);
1524 ck_assert(strneq("0.0.1", "", 6) == false);
1525 ck_assert(strneq("foo", NULL, 5) == false);
1526 ck_assert(strneq(NULL, "foo", 5) == false);
1527 ck_assert(strneq("0.0.1", "0.0.1", 6) == true);
1528 }
1529 END_TEST
1530
START_TESTnull1531 START_TEST(basename_test)
1532 {
1533 struct test {
1534 const char *path;
1535 const char *expected;
1536 } tests[] = {
1537 { "a", "a" },
1538 { "foo.c", "foo.c" },
1539 { "foo", "foo" },
1540 { "/path/to/foo.h", "foo.h" },
1541 { "../bar.foo", "bar.foo" },
1542 { "./bar.foo.baz", "bar.foo.baz" },
1543 { "./", NULL },
1544 { "/", NULL },
1545 { "/bar/", NULL },
1546 { "/bar", "bar" },
1547 { "", NULL },
1548 };
1549
1550 ARRAY_FOR_EACH(tests, t) {
1551 const char *result = safe_basename(t->path);
1552 if (t->expected == NULL)
1553 ck_assert(result == NULL);
1554 else
1555 ck_assert_str_eq(result, t->expected);
1556 }
1557 }
1558 END_TEST
START_TESTnull1559 START_TEST(trunkname_test)
1560 {
1561 struct test {
1562 const char *path;
1563 const char *expected;
1564 } tests[] = {
1565 { "foo.c", "foo" },
1566 { "/path/to/foo.h", "foo" },
1567 { "/path/to/foo", "foo" },
1568 { "../bar.foo", "bar" },
1569 { "./bar.foo.baz", "bar.foo" },
1570 { "./", "" },
1571 { "/", "" },
1572 { "/bar/", "" },
1573 { "/bar", "bar" },
1574 { "", "" },
1575 };
1576
1577 ARRAY_FOR_EACH(tests, t) {
1578 char *result = trunkname(t->path);
1579 ck_assert_str_eq(result, t->expected);
1580 free(result);
1581 }
1582 }
1583 END_TEST
1584
1585 static Suite *
litest_utils_suite(void)1586 litest_utils_suite(void)
1587 {
1588 TCase *tc;
1589 Suite *s;
1590
1591 s = suite_create("litest:utils");
1592 tc = tcase_create("utils");
1593
1594 tcase_add_test(tc, array_for_each);
1595
1596 tcase_add_test(tc, bitfield_helpers);
1597 tcase_add_test(tc, matrix_helpers);
1598 tcase_add_test(tc, ratelimit_helpers);
1599 tcase_add_test(tc, dpi_parser);
1600 tcase_add_test(tc, wheel_click_parser);
1601 tcase_add_test(tc, wheel_click_count_parser);
1602 tcase_add_test(tc, dimension_prop_parser);
1603 tcase_add_test(tc, reliability_prop_parser);
1604 tcase_add_test(tc, calibration_prop_parser);
1605 tcase_add_test(tc, range_prop_parser);
1606 tcase_add_test(tc, boolean_prop_parser);
1607 tcase_add_test(tc, evcode_prop_parser);
1608 tcase_add_test(tc, input_prop_parser);
1609 tcase_add_test(tc, evdev_abs_parser);
1610 tcase_add_test(tc, safe_atoi_test);
1611 tcase_add_test(tc, safe_atoi_base_16_test);
1612 tcase_add_test(tc, safe_atoi_base_8_test);
1613 tcase_add_test(tc, safe_atou_test);
1614 tcase_add_test(tc, safe_atou_base_16_test);
1615 tcase_add_test(tc, safe_atou_base_8_test);
1616 tcase_add_test(tc, safe_atod_test);
1617 tcase_add_test(tc, strsplit_test);
1618 tcase_add_test(tc, double_array_from_string_test);
1619 tcase_add_test(tc, strargv_test);
1620 tcase_add_test(tc, kvsplit_double_test);
1621 tcase_add_test(tc, strjoin_test);
1622 tcase_add_test(tc, strstrip_test);
1623 tcase_add_test(tc, strendswith_test);
1624 tcase_add_test(tc, strstartswith_test);
1625 tcase_add_test(tc, strsanitize_test);
1626 tcase_add_test(tc, time_conversion);
1627 tcase_add_test(tc, human_time);
1628
1629 tcase_add_test(tc, list_test_insert);
1630 tcase_add_test(tc, list_test_append);
1631 tcase_add_test(tc, list_test_foreach);
1632 tcase_add_test(tc, strverscmp_test);
1633 tcase_add_test(tc, streq_test);
1634 tcase_add_test(tc, strneq_test);
1635 tcase_add_test(tc, trunkname_test);
1636 tcase_add_test(tc, basename_test);
1637
1638 suite_add_tcase(s, tc);
1639
1640 return s;
1641 }
1642
main(int argc, char **argv)1643 int main(int argc, char **argv)
1644 {
1645 int nfailed;
1646 Suite *s;
1647 SRunner *sr;
1648
1649 s = litest_utils_suite();
1650 sr = srunner_create(s);
1651
1652 srunner_run_all(sr, CK_ENV);
1653 nfailed = srunner_ntests_failed(sr);
1654 srunner_free(sr);
1655
1656 return (nfailed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
1657 }
1658