mirror of https://github.com/nirenjan/libx52.git
test: Add tests for x52evtest and x52joytest
This change adds additional code coverage test cases for the evtest and joytest modules.lipc-refactor
parent
fdf884cb1c
commit
772017661d
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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 */
|
||||
|
|
@ -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 <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <setjmp.h>
|
||||
#include <cmocka.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
#include <sys/time.h>
|
||||
|
||||
#include <libx52/libx52io.h>
|
||||
#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]);
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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 <stddef.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libx52/libx52.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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 <libx52/libx52.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <setjmp.h>
|
||||
#include <cmocka.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
@ -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 <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\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 ""
|
||||
|
|
|
|||
15
po/xx_PL.po
15
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 <nirenjan@gmail.com>\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
|
||||
|
|
|
|||
Loading…
Reference in New Issue