From 772017661dbf00cf3e0c3a82dda9d30778d1e421 Mon Sep 17 00:00:00 2001 From: nirenjan Date: Mon, 20 Apr 2026 21:56:58 -0700 Subject: [PATCH] test: Add tests for x52evtest and x52joytest This change adds additional code coverage test cases for the evtest and joytest modules. --- evtest/ev_denoise.c | 25 ++++++ evtest/ev_denoise.h | 19 +++++ evtest/ev_denoise_test.c | 136 +++++++++++++++++++++++++++++++ evtest/ev_test.c | 17 +--- evtest/meson.build | 9 +- joytest/libx52_mock.c | 121 +++++++++++++++++++++++++++ joytest/meson.build | 46 ++++++++++- joytest/x52_test.c | 64 +++++---------- joytest/x52_test_args.c | 50 ++++++++++++ joytest/x52_test_args.h | 32 ++++++++ joytest/x52_test_args_test.c | 154 +++++++++++++++++++++++++++++++++++ po/libx52.pot | 12 +-- po/xx_PL.po | 15 ++-- 13 files changed, 625 insertions(+), 75 deletions(-) create mode 100644 evtest/ev_denoise.c create mode 100644 evtest/ev_denoise.h create mode 100644 evtest/ev_denoise_test.c create mode 100644 joytest/libx52_mock.c create mode 100644 joytest/x52_test_args.c create mode 100644 joytest/x52_test_args.h create mode 100644 joytest/x52_test_args_test.c diff --git a/evtest/ev_denoise.c b/evtest/ev_denoise.c new file mode 100644 index 0000000..a0cbc87 --- /dev/null +++ b/evtest/ev_denoise.c @@ -0,0 +1,25 @@ +/* + * Saitek X52 Pro MFD & LED driver - Event test axis denoise helpers + * + * Copyright (C) 2026 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 + */ + +#include "ev_denoise.h" + +int32_t evtest_axis_denoise_mask(int32_t axis_max) +{ + return ~(axis_max >> 6); +} + +bool evtest_axis_changed(int32_t last, int32_t curr, int32_t mask, bool denoise_enabled) +{ + if (last == curr) { + return false; + } + if (!denoise_enabled) { + return true; + } + return (last & mask) != (curr & mask); +} diff --git a/evtest/ev_denoise.h b/evtest/ev_denoise.h new file mode 100644 index 0000000..defb9cd --- /dev/null +++ b/evtest/ev_denoise.h @@ -0,0 +1,19 @@ +/* + * Saitek X52 Pro MFD & LED driver - Event test axis denoise helpers + * + * Copyright (C) 2026 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 + */ + +#ifndef EVTEST_EV_DENOISE_H +#define EVTEST_EV_DENOISE_H + +#include +#include + +int32_t evtest_axis_denoise_mask(int32_t axis_max); + +bool evtest_axis_changed(int32_t last, int32_t curr, int32_t mask, bool denoise_enabled); + +#endif /* EVTEST_EV_DENOISE_H */ diff --git a/evtest/ev_denoise_test.c b/evtest/ev_denoise_test.c new file mode 100644 index 0000000..e4e49d1 --- /dev/null +++ b/evtest/ev_denoise_test.c @@ -0,0 +1,136 @@ +/* + * Saitek X52 Pro MFD & LED driver - Event test axis denoise unit tests + * + * Copyright (C) 2026 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include "ev_denoise.h" + +static void test_mask_small_max_all_bits(void **state) +{ + (void)state; + /* (max >> 6) == 0 => mask is ~0 => -1 as int32_t */ + assert_int_equal(evtest_axis_denoise_mask(0), -1); + assert_int_equal(evtest_axis_denoise_mask(63), -1); +} + +static void test_mask_large_max_clears_low_bits(void **state) +{ + (void)state; + int32_t max = 1023; + int32_t mask = evtest_axis_denoise_mask(max); + + /* 1023 >> 6 == 15; ~15 as int32_t is -16 (low four bits clear in mask) */ + assert_int_equal(mask, (int32_t) ~15); + assert_int_not_equal(mask, -1); + /* Noise within cleared low bits should not matter when masked */ + assert_int_equal(100 & mask, 101 & mask); +} + +/* + * (max >> 6) is 0 for max in [0, 63] and becomes 1 at max == 64, so the mask + * flips from all bits set (-1) to clearing the least significant bit (-2). + */ +static void test_mask_boundary_63_vs_64(void **state) +{ + (void)state; + + assert_int_equal(evtest_axis_denoise_mask(63), -1); + assert_int_equal(evtest_axis_denoise_mask(64), -2); + assert_int_equal(evtest_axis_denoise_mask(64), (int32_t) ~(64 >> 6)); +} + +static void test_axis_changed_mask_boundary_lsb_noise(void **state) +{ + (void)state; + int32_t mask63 = evtest_axis_denoise_mask(63); + int32_t mask64 = evtest_axis_denoise_mask(64); + + /* Adjacent values differing only in bit 0: masked equal with -2, not with -1 */ + assert_int_equal(100 & mask64, 101 & mask64); + assert_int_not_equal(100 & mask63, 101 & mask63); + + assert_false(evtest_axis_changed(100, 101, mask64, true)); + assert_true(evtest_axis_changed(100, 101, mask63, true)); +} + +static void test_mask_4095_and_axis_changed_low_six_bits(void **state) +{ + (void)state; + int32_t max = 4095; + int32_t mask = evtest_axis_denoise_mask(max); + + /* 4095 >> 6 == 63; ~63 as int32_t is -64 (low six bits clear in mask) */ + assert_int_equal(mask, (int32_t) ~63); + assert_int_equal(mask, -64); + + assert_int_equal(0 & mask, 31 & mask); + assert_false(evtest_axis_changed(0, 31, mask, true)); + + assert_int_not_equal(0 & mask, 64 & mask); + assert_true(evtest_axis_changed(0, 64, mask, true)); +} + +static void test_axis_changed_equal_raw(void **state) +{ + (void)state; + assert_false(evtest_axis_changed(500, 500, -1, true)); + assert_false(evtest_axis_changed(500, 500, -1, false)); +} + +static void test_axis_changed_unequal_denoise_off(void **state) +{ + (void)state; + assert_true(evtest_axis_changed(100, 101, -1, false)); +} + +static void test_axis_changed_equal_after_mask_denoise_on(void **state) +{ + (void)state; + int32_t mask = evtest_axis_denoise_mask(1023); + + assert_false(evtest_axis_changed(100, 101, mask, true)); +} + +static void test_axis_changed_still_change_after_mask(void **state) +{ + (void)state; + int32_t mask = evtest_axis_denoise_mask(1023); + + assert_true(evtest_axis_changed(96, 112, mask, true)); +} + +static void test_axis_changed_full_mask_any_raw_diff(void **state) +{ + (void)state; + /* With mask -1, (v & -1) == v, so any raw difference is a change */ + assert_true(evtest_axis_changed(10, 11, -1, true)); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_mask_small_max_all_bits), + cmocka_unit_test(test_mask_large_max_clears_low_bits), + cmocka_unit_test(test_mask_boundary_63_vs_64), + cmocka_unit_test(test_axis_changed_mask_boundary_lsb_noise), + cmocka_unit_test(test_mask_4095_and_axis_changed_low_six_bits), + cmocka_unit_test(test_axis_changed_equal_raw), + cmocka_unit_test(test_axis_changed_unequal_denoise_off), + cmocka_unit_test(test_axis_changed_equal_after_mask_denoise_on), + cmocka_unit_test(test_axis_changed_still_change_after_mask), + cmocka_unit_test(test_axis_changed_full_mask_any_raw_diff), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/evtest/ev_test.c b/evtest/ev_test.c index 45962ff..44077bf 100644 --- a/evtest/ev_test.c +++ b/evtest/ev_test.c @@ -18,6 +18,7 @@ #include #include +#include "ev_denoise.h" #include "gettext.h" /* @@ -97,7 +98,7 @@ int main(void) * ~(max >> 6) which will do nothing for the axis with a small * range, but reduce the noise on those with a larger range. */ - denoise_mask[i] = ~(max >> 6); + denoise_mask[i] = evtest_axis_denoise_mask(max); } } @@ -143,18 +144,8 @@ int main(void) /* Get the current timeval - we don't need a timezone */ gettimeofday(&tv, NULL); for (int axis = 0; axis < LIBX52IO_AXIS_MAX; axis++) { - if (last.axis[axis] != curr.axis[axis]) { - /* Account for denoising */ - if (denoise) { - int32_t last_v = last.axis[axis] & denoise_mask[axis]; - int32_t curr_v = curr.axis[axis] & denoise_mask[axis]; - - if (last_v == curr_v) { - /* Within the noise threshold */ - continue; - } - } - + if (evtest_axis_changed(last.axis[axis], curr.axis[axis], + denoise_mask[axis], denoise)) { printf(_("Event @ %ld.%06ld: %s, value %d\n"), (long int)tv.tv_sec, (long int)tv.tv_usec, libx52io_axis_to_str(axis), curr.axis[axis]); diff --git a/evtest/meson.build b/evtest/meson.build index 435b9be..a5d7305 100644 --- a/evtest/meson.build +++ b/evtest/meson.build @@ -1,6 +1,13 @@ # x52evtest -executable('x52evtest', 'ev_test.c', +executable('x52evtest', ['ev_test.c', 'ev_denoise.c'], install: true, include_directories: includes, dependencies: [dep_intl], link_with: [lib_libx52io]) + +ev_denoise_test = executable('ev-denoise-test', ['ev_denoise_test.c', 'ev_denoise.c'], + build_by_default: false, + dependencies: [dep_cmocka], + include_directories: includes, +) +test('ev-denoise', ev_denoise_test, protocol: 'tap') diff --git a/joytest/libx52_mock.c b/joytest/libx52_mock.c new file mode 100644 index 0000000..d02375b --- /dev/null +++ b/joytest/libx52_mock.c @@ -0,0 +1,121 @@ +/* + * Saitek X52 Pro MFD & LED driver + * + * Copyright (C) 2026 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 + */ + +#include +#include +#include + +#include + +/* Opaque device: any unique non-NULL address is enough for joytest. */ +static char joytest_mock_dev_storage; + +int libx52_init(libx52_device **dev) +{ + if (!dev) { + return LIBX52_ERROR_INVALID_PARAM; + } + *dev = (libx52_device *)&joytest_mock_dev_storage; + return LIBX52_SUCCESS; +} + +void libx52_exit(libx52_device *dev) +{ + (void)dev; +} + +const char *libx52_strerror(libx52_error_code error) +{ + (void)error; + // We don't actually use this in the mock, but it's required by the API + return ""; +} + +int libx52_check_feature(libx52_device *x52, libx52_feature feature) +{ + (void)x52; + (void)feature; + // This is needed to satisfy the API, assume that the device supports LED control + return LIBX52_SUCCESS; +} + +int libx52_set_text(libx52_device *x52, uint8_t line, const char *text, uint8_t length) +{ + (void)x52; + (void)line; + (void)text; + (void)length; + return LIBX52_SUCCESS; +} + +int libx52_set_led_state(libx52_device *x52, libx52_led_id led, libx52_led_state state) +{ + (void)x52; + (void)led; + (void)state; + return LIBX52_SUCCESS; +} + +int libx52_set_clock(libx52_device *x52, time_t t, int local) +{ + (void)x52; + (void)t; + (void)local; + return LIBX52_SUCCESS; +} + +int libx52_set_clock_timezone(libx52_device *x52, libx52_clock_id clock, int offset) +{ + (void)x52; + (void)clock; + (void)offset; + return LIBX52_SUCCESS; +} + +int libx52_set_clock_format(libx52_device *x52, libx52_clock_id clock, libx52_clock_format format) +{ + (void)x52; + (void)clock; + (void)format; + return LIBX52_SUCCESS; +} + +int libx52_set_date_format(libx52_device *x52, libx52_date_format format) +{ + (void)x52; + (void)format; + return LIBX52_SUCCESS; +} + +int libx52_set_brightness(libx52_device *x52, uint8_t mfd, uint16_t brightness) +{ + (void)x52; + (void)mfd; + (void)brightness; + return LIBX52_SUCCESS; +} + +int libx52_set_shift(libx52_device *x52, uint8_t state) +{ + (void)x52; + (void)state; + return LIBX52_SUCCESS; +} + +int libx52_set_blink(libx52_device *x52, uint8_t state) +{ + (void)x52; + (void)state; + return LIBX52_SUCCESS; +} + +int libx52_update(libx52_device *x52) +{ + (void)x52; + return LIBX52_SUCCESS; +} diff --git a/joytest/meson.build b/joytest/meson.build index 99688fd..3a5bc96 100644 --- a/joytest/meson.build +++ b/joytest/meson.build @@ -1,10 +1,52 @@ -# x52test -executable('x52test', +joytest_sources = files( 'x52_test.c', + 'x52_test_args.c', 'x52_test_mfd.c', 'x52_test_led.c', 'x52_test_clock.c', +) + +joytest_libx52_mock = static_library('joytest-libx52-mock', + 'libx52_mock.c', + include_directories: includes, +) + +# x52test +exe_x52test = executable('x52test', + joytest_sources, install: true, dependencies: [dep_intl], include_directories: includes, link_with: [lib_libx52]) + +exe_x52test_mock = executable('x52test-mock', + joytest_sources, + install: false, + dependencies: [dep_intl], + include_directories: includes, + link_with: [joytest_libx52_mock], +) + +sh = find_program('sh') +test('x52test-mock', + sh, + args: [ + '-c', + 'printf "\n" | env NO_DELAY=1 @0@'.format(exe_x52test_mock.full_path()), + ], + depends: exe_x52test_mock, + protocol: 'exitcode', + timeout: 60, +) + +test('x52test-help', exe_x52test, args: ['help'], protocol: 'exitcode') +test('x52test-help-dashdash', exe_x52test, args: ['--help'], protocol: 'exitcode') +test('x52test-bad-arg', exe_x52test, args: ['not-a-test-id'], protocol: 'exitcode', should_fail: true) + +x52test_args_test = executable('x52test-args-test', + ['x52_test_args_test.c', 'x52_test_args.c'], + build_by_default: false, + dependencies: [dep_cmocka], + include_directories: includes, +) +test('x52test-args', x52test_args_test, protocol: 'tap') diff --git a/joytest/x52_test.c b/joytest/x52_test.c index 3c06522..2e7505c 100644 --- a/joytest/x52_test.c +++ b/joytest/x52_test.c @@ -1,7 +1,7 @@ /* * Saitek X52 Pro MFD & LED driver * - * Copyright (C) 2012-2015 Nirenjan Krishnan (nirenjan@nirenjan.org) + * Copyright (C) 2012-2026 Nirenjan Krishnan (nirenjan@nirenjan.org) * * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 */ @@ -17,6 +17,8 @@ #include #include "x52_test_common.h" +#include "x52_test_args.h" + libx52_device *dev; int test_exit; bool nodelay; @@ -186,11 +188,7 @@ static void usage(void) puts(""); } -struct test_map { - const char *cmd; - int test_bitmap; -}; -const struct test_map tests[] = { +const struct x52test_cmd tests[] = { #define X(en, cmd, desc) { #cmd, TEST_ ##en }, TESTS #undef X @@ -199,10 +197,8 @@ const struct test_map tests[] = { int main(int argc, char **argv) { - int test_list; - int i; - const struct test_map *test; - int found; + struct x52test_argv_result parsed; + int ret = 0; /* Initialize gettext */ #if ENABLE_NLS @@ -212,50 +208,28 @@ int main(int argc, char **argv) #endif /* Usage: x52test [list of tests] */ - if (argc == 1) { - /* Run all tests, if none specified */ - test_list = TEST_ALL; - } else { - /* Initialize the test list to run no tests, the commands - * will enable the selective tests - */ - test_list = 0; + x52test_parse_argv(argc, argv, tests, TEST_ALL, &parsed); + + if (parsed.status == X52TEST_ARGV_HELP) { + printf(_("Usage: %s [list of tests]\n\n"), argv[0]); + usage(); + return 0; } - for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "help") || - !strcmp(argv[i], "--help")) { - - /* Display help string and exit */ - printf(_("Usage: %s [list of tests]\n\n"), argv[0]); - usage(); - return 0; - } else { - found = 0; - for (test = tests; test->cmd; test++) { - if (!strcmp(argv[i], test->cmd)) { - test_list |= test->test_bitmap; - found = 1; - break; - } - } - - if (found == 0) { - printf(_("Unrecognized test identifier: %s\n\n"), argv[i]); - usage(); - return 1; - } - } + if (parsed.status == X52TEST_ARGV_UNKNOWN) { + printf(_("Unrecognized test identifier: %s\n\n"), argv[parsed.bad_arg_index]); + usage(); + return 1; } /* Initialize the nodelay variable */ nodelay = (getenv("LD_PRELOAD") != NULL || getenv("NO_DELAY") != NULL); - if (test_list) { - i = run_tests(test_list); + if (parsed.test_bitmap) { + ret = run_tests(parsed.test_bitmap); } else { puts(_("Not running any tests")); } - return i; + return ret; } diff --git a/joytest/x52_test_args.c b/joytest/x52_test_args.c new file mode 100644 index 0000000..5a73b8a --- /dev/null +++ b/joytest/x52_test_args.c @@ -0,0 +1,50 @@ +/* + * Saitek X52 Pro MFD & LED driver + * + * Copyright (C) 2026 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 + */ + +#include "x52_test_args.h" +#include + +void x52test_parse_argv(int argc, char **argv, const struct x52test_cmd *cmds, + int test_all_bitmap, struct x52test_argv_result *out) +{ + int i; + const struct x52test_cmd *c; + + out->status = X52TEST_ARGV_OK; + out->bad_arg_index = 0; + + if (argc == 1) { + out->test_bitmap = test_all_bitmap; + return; + } + + out->test_bitmap = 0; + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "help") || !strcmp(argv[i], "--help")) { + out->status = X52TEST_ARGV_HELP; + return; + } + + int found = 0; + + for (c = cmds; c->cmd; c++) { + if (!strcmp(argv[i], c->cmd)) { + out->test_bitmap |= c->test_bitmap; + found = 1; + break; + } + } + + if (!found) { + out->status = X52TEST_ARGV_UNKNOWN; + out->bad_arg_index = i; + return; + } + } +} diff --git a/joytest/x52_test_args.h b/joytest/x52_test_args.h new file mode 100644 index 0000000..4a5e87c --- /dev/null +++ b/joytest/x52_test_args.h @@ -0,0 +1,32 @@ +/* + * Saitek X52 Pro MFD & LED driver + * + * Copyright (C) 2026 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 + */ + +#ifndef X52_TEST_ARGS_H +#define X52_TEST_ARGS_H + +enum x52test_argv_status { + X52TEST_ARGV_OK, + X52TEST_ARGV_HELP, + X52TEST_ARGV_UNKNOWN, +}; + +struct x52test_cmd { + const char *cmd; + int test_bitmap; +}; + +struct x52test_argv_result { + enum x52test_argv_status status; + int test_bitmap; + int bad_arg_index; +}; + +void x52test_parse_argv(int argc, char **argv, const struct x52test_cmd *cmds, + int test_all_bitmap, struct x52test_argv_result *out); + +#endif /* X52_TEST_ARGS_H */ diff --git a/joytest/x52_test_args_test.c b/joytest/x52_test_args_test.c new file mode 100644 index 0000000..1dcfd60 --- /dev/null +++ b/joytest/x52_test_args_test.c @@ -0,0 +1,154 @@ +/* + * Saitek X52 Pro MFD & LED driver - x52test argv parsing unit tests + * + * Copyright (C) 2026 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include "x52_test_args.h" + +#define BIT_A (1 << 0) +#define BIT_B (1 << 1) +#define BIT_C (1 << 2) +#define TEST_ALL_SYN (BIT_A | BIT_B | BIT_C) + +static const struct x52test_cmd syn_cmds[] = { + { "a", BIT_A }, + { "b", BIT_B }, + { "c", BIT_C }, + { NULL, 0 }, +}; + +static void test_argc_one_is_test_all(void **state) +{ + (void)state; + char *argv[] = { (char *)"prog", NULL }; + struct x52test_argv_result r; + + x52test_parse_argv(1, argv, syn_cmds, TEST_ALL_SYN, &r); + assert_int_equal(r.status, X52TEST_ARGV_OK); + assert_int_equal(r.test_bitmap, TEST_ALL_SYN); +} + +static void test_single_cmd(void **state) +{ + (void)state; + char *argv[] = { (char *)"prog", (char *)"b", NULL }; + struct x52test_argv_result r; + + x52test_parse_argv(2, argv, syn_cmds, TEST_ALL_SYN, &r); + assert_int_equal(r.status, X52TEST_ARGV_OK); + assert_int_equal(r.test_bitmap, BIT_B); +} + +static void test_multi_cmd_ors(void **state) +{ + (void)state; + char *argv[] = { (char *)"prog", (char *)"a", (char *)"c", NULL }; + struct x52test_argv_result r; + + x52test_parse_argv(3, argv, syn_cmds, TEST_ALL_SYN, &r); + assert_int_equal(r.status, X52TEST_ARGV_OK); + assert_int_equal(r.test_bitmap, BIT_A | BIT_C); +} + +static void test_duplicate_cmd_ors_same_bit(void **state) +{ + (void)state; + char *argv[] = { (char *)"prog", (char *)"a", (char *)"a", NULL }; + struct x52test_argv_result r; + + x52test_parse_argv(3, argv, syn_cmds, TEST_ALL_SYN, &r); + assert_int_equal(r.status, X52TEST_ARGV_OK); + assert_int_equal(r.test_bitmap, BIT_A); +} + +static void test_help_keyword(void **state) +{ + (void)state; + char *argv[] = { (char *)"prog", (char *)"help", NULL }; + struct x52test_argv_result r; + + x52test_parse_argv(2, argv, syn_cmds, TEST_ALL_SYN, &r); + assert_int_equal(r.status, X52TEST_ARGV_HELP); +} + +static void test_dashdash_help(void **state) +{ + (void)state; + char *argv[] = { (char *)"prog", (char *)"--help", NULL }; + struct x52test_argv_result r; + + x52test_parse_argv(2, argv, syn_cmds, TEST_ALL_SYN, &r); + assert_int_equal(r.status, X52TEST_ARGV_HELP); +} + +static void test_help_after_other_arg(void **state) +{ + (void)state; + char *argv[] = { (char *)"prog", (char *)"a", (char *)"help", NULL }; + struct x52test_argv_result r; + + x52test_parse_argv(3, argv, syn_cmds, TEST_ALL_SYN, &r); + assert_int_equal(r.status, X52TEST_ARGV_HELP); +} + +static void test_help_before_other_arg(void **state) +{ + (void)state; + char *argv[] = { (char *)"prog", (char *)"help", (char *)"a", (char *)"b", NULL }; + struct x52test_argv_result r; + + x52test_parse_argv(4, argv, syn_cmds, TEST_ALL_SYN, &r); + assert_int_equal(r.status, X52TEST_ARGV_HELP); + assert_int_equal(r.test_bitmap, 0); +} + +static void test_unknown_bad_index(void **state) +{ + (void)state; + char *argv[] = { (char *)"prog", (char *)"a", (char *)"nope", NULL }; + struct x52test_argv_result r; + + x52test_parse_argv(3, argv, syn_cmds, TEST_ALL_SYN, &r); + assert_int_equal(r.status, X52TEST_ARGV_UNKNOWN); + assert_int_equal(r.bad_arg_index, 2); +} + +static void test_unknown_first_arg_index(void **state) +{ + (void)state; + char *argv[] = { (char *)"prog", (char *)"xyz", NULL }; + struct x52test_argv_result r; + + x52test_parse_argv(2, argv, syn_cmds, TEST_ALL_SYN, &r); + assert_int_equal(r.status, X52TEST_ARGV_UNKNOWN); + assert_int_equal(r.bad_arg_index, 1); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_argc_one_is_test_all), + cmocka_unit_test(test_single_cmd), + cmocka_unit_test(test_multi_cmd_ors), + cmocka_unit_test(test_duplicate_cmd_ors_same_bit), + cmocka_unit_test(test_help_keyword), + cmocka_unit_test(test_dashdash_help), + cmocka_unit_test(test_help_after_other_arg), + cmocka_unit_test(test_help_before_other_arg), + cmocka_unit_test(test_unknown_bad_index), + cmocka_unit_test(test_unknown_first_arg_index), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/po/libx52.pot b/po/libx52.pot index 70bac5b..504b65a 100644 --- a/po/libx52.pot +++ b/po/libx52.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: libx52 0.3.3\n" "Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n" -"POT-Creation-Date: 2026-04-04 23:11-0700\n" +"POT-Creation-Date: 2026-04-20 21:55-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -261,26 +261,26 @@ msgstr "" msgid "No state change" msgstr "" -#: evtest/ev_test.c:110 +#: evtest/ev_test.c:111 #, c-format msgid "Device ID: vendor 0x%04x product 0x%04x version 0x%04x\n" msgstr "" -#: evtest/ev_test.c:114 +#: evtest/ev_test.c:115 #, c-format msgid "Device name: \"%s %s\"\n" msgstr "" -#: evtest/ev_test.c:117 +#: evtest/ev_test.c:118 #, c-format msgid "Serial number: \"%s\"\n" msgstr "" -#: evtest/ev_test.c:118 +#: evtest/ev_test.c:119 msgid "Testing (interrupt to exit)\n" msgstr "" -#: evtest/ev_test.c:158 evtest/ev_test.c:166 +#: evtest/ev_test.c:149 evtest/ev_test.c:157 #, c-format msgid "Event @ %ld.%06ld: %s, value %d\n" msgstr "" diff --git a/po/xx_PL.po b/po/xx_PL.po index 5568357..d5fb0f5 100644 --- a/po/xx_PL.po +++ b/po/xx_PL.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: libx52 0.3.3\n" "Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n" -"POT-Creation-Date: 2026-04-04 23:11-0700\n" +"POT-Creation-Date: 2026-04-20 21:55-0700\n" "PO-Revision-Date: 2026-04-04 12:00-0700\n" "Last-Translator: Nirenjan Krishnan \n" "Language-Team: Dummy Language for testing i18n\n" @@ -261,26 +261,26 @@ msgstr "Unableay otay itewray eventay" msgid "No state change" msgstr "Onay atestay angechay" -#: evtest/ev_test.c:110 +#: evtest/ev_test.c:111 #, c-format msgid "Device ID: vendor 0x%04x product 0x%04x version 0x%04x\n" msgstr "Eviceday IDay: endorvay 0x%04x oductpray 0x%04x ersionvay 0x%04x\n" -#: evtest/ev_test.c:114 +#: evtest/ev_test.c:115 #, c-format msgid "Device name: \"%s %s\"\n" msgstr "Eviceday amenay: \"%s %s\"\n" -#: evtest/ev_test.c:117 +#: evtest/ev_test.c:118 #, c-format msgid "Serial number: \"%s\"\n" msgstr "Erialsay umbernay: \"%s\"\n" -#: evtest/ev_test.c:118 +#: evtest/ev_test.c:119 msgid "Testing (interrupt to exit)\n" msgstr "Estingtay (interruptay otay exitay)\n" -#: evtest/ev_test.c:158 evtest/ev_test.c:166 +#: evtest/ev_test.c:149 evtest/ev_test.c:157 #, c-format msgid "Event @ %ld.%06ld: %s, value %d\n" msgstr "Eventay @ %ld.%06ld: %s, aluevay %d\n" @@ -838,8 +838,7 @@ msgstr "" #: daemon/keyboard_layout.c:83 #, c-format msgid "Could not load keyboard layout from %s/x52d (%s)" -msgstr "" -"ouldCay otnay oadlay eyboardkay ayoutlay omfray %s/x52d (%s)" +msgstr "ouldCay otnay oadlay eyboardkay ayoutlay omfray %s/x52d (%s)" #: daemon/keyboard_layout.c:92 #, c-format