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