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