test: Add tests for x52evtest and x52joytest

This change adds additional code coverage test cases for the evtest and
joytest modules.
lipc-refactor
nirenjan 2026-04-20 21:56:58 -07:00
parent fdf884cb1c
commit 772017661d
13 changed files with 625 additions and 75 deletions

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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]);

View File

@ -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')

View File

@ -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;
}

View File

@ -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')

View File

@ -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);
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "help") ||
!strcmp(argv[i], "--help")) {
/* Display help string and exit */
if (parsed.status == X52TEST_ARGV_HELP) {
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]);
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;
}

View File

@ -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;
}
}
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 ""

View File

@ -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