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