xref: /third_party/libinput/test/test-utils.c (revision a46c0ec8)
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
44START_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}
93END_TEST
94
95START_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}
130END_TEST
131
132START_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}
207END_TEST
208
209START_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}
247END_TEST
248
249struct parser_test {
250	char *tag;
251	int expected_value;
252};
253
254START_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}
291END_TEST
292
293START_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}
318END_TEST
319
320START_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}
348END_TEST
349
350START_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}
395END_TEST
396
397START_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}
433END_TEST
434
435START_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}
484END_TEST
485
486START_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}
524END_TEST
525
526START_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}
556END_TEST
557
558START_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}
634END_TEST
635
636START_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}
681END_TEST
682
683START_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}
757END_TEST
758
759START_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}
768END_TEST
769
770START_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}
799END_TEST
800
801struct atoi_test {
802	char *str;
803	bool success;
804	int val;
805};
806
807START_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}
840END_TEST
841
842START_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}
874END_TEST
875
876START_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}
911END_TEST
912
913struct atou_test {
914	char *str;
915	bool success;
916	unsigned int val;
917};
918
919START_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}
951END_TEST
952
953START_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}
985END_TEST
986
987START_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}
1022END_TEST
1023
1024START_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}
1069END_TEST
1070
1071START_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}
1120END_TEST
1121
1122START_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}
1164END_TEST
1165
1166START_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}
1201END_TEST
1202
1203START_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}
1251END_TEST
1252
1253START_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}
1289END_TEST
1290
1291START_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}
1327END_TEST
1328
1329START_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}
1351END_TEST
1352
1353START_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}
1375END_TEST
1376
1377START_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}
1400END_TEST
1401
1402START_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}
1431END_TEST
1432
1433START_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}
1461END_TEST
1462
1463START_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}
1494END_TEST
1495
1496START_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}
1507END_TEST
1508
1509START_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}
1518END_TEST
1519
1520START_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}
1529END_TEST
1530
1531START_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}
1558END_TEST
1559START_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}
1583END_TEST
1584
1585static Suite *
1586litest_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
1643int 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