From bf9b1bdfbd3889d102c97ecd4d4a2e10a213d876 Mon Sep 17 00:00:00 2001 From: nirenjan Date: Tue, 16 Jun 2020 17:30:11 -0700 Subject: [PATCH] Remove manual tests in favor of cmocka Prior to this change, we needed to add a manual override function to mock the vendor command. Given that cmocka has built-in support for mocking functions, it's better to use that instead. This change simply removes the manual override and any tests that rely on it. --- configure.ac | 6 ++ lib/libx52/Makefile.am | 19 +---- lib/libx52/test_blink_shift.c | 59 ------------- lib/libx52/test_common.c | 155 ---------------------------------- lib/libx52/test_common.h | 94 --------------------- lib/libx52/test_led.c | 122 -------------------------- lib/libx52/test_offset.c | 60 ------------- lib/libx52/x52_common.h | 4 - lib/libx52/x52_control.c | 25 ++---- lib/libx52/x52_core.c | 4 - 10 files changed, 17 insertions(+), 531 deletions(-) delete mode 100644 lib/libx52/test_blink_shift.c delete mode 100644 lib/libx52/test_common.c delete mode 100644 lib/libx52/test_common.h delete mode 100644 lib/libx52/test_led.c delete mode 100644 lib/libx52/test_offset.c diff --git a/configure.ac b/configure.ac index 6599a1e..6d9f155 100644 --- a/configure.ac +++ b/configure.ac @@ -62,6 +62,12 @@ AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([Doxyfile])], [AC_MSG_WARN(["Doxygen not found; continuing without doxygen support"])]) +# cmocka unit tests +AX_PKG_CHECK_MODULES([CMOCKA], [cmocka], [], [have_cmocka=yes], [have_cmocka=no]) +AM_CONDITIONAL([HAVE_CMOCKA], [test "x$have_cmocka" = xyes]) +AM_COND_IF([HAVE_CMOCKA], [], + [AC_MSG_WARN(["cmocka not found; disabling unit test build"])]) + # Check for the presence of tm_gmtoff in struct tm. If we have this, then we # can use it to determine the true GMT offset AC_CHECK_MEMBERS([struct tm.tm_gmtoff],, diff --git a/lib/libx52/Makefile.am b/lib/libx52/Makefile.am index 7c01736..50cb4e5 100644 --- a/lib/libx52/Makefile.am +++ b/lib/libx52/Makefile.am @@ -31,25 +31,12 @@ x52include_HEADERS = libx52.h # pkg-config files pkgconfig_DATA = libx52.pc -check_PROGRAMS = test_offset test_led test_blink_shift - -test_offset_SOURCES = test_offset.c test_common.c -test_offset_CFLAGS = @LIBUSB_CFLAGS@ -test_offset_LDADD = libx52.la - -test_led_SOURCES = test_led.c test_common.c -test_led_CFLAGS = @LIBUSB_CFLAGS@ -test_led_LDADD = libx52.la - -test_blink_shift_SOURCES = test_blink_shift.c test_common.c -test_blink_shift_CFLAGS = @LIBUSB_CFLAGS@ -test_blink_shift_LDADD = libx52.la - +if HAVE_CMOCKA LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tap-driver.sh -TESTS = test_offset test_led test_blink_shift +endif # Extra files that need to be in the distribution -EXTRA_DIST = libx52.h x52_commands.h x52_common.h test_common.h README.md +EXTRA_DIST = libx52.h x52_commands.h x52_common.h README.md # Add documentation files to the distribution EXTRA_DIST += \ diff --git a/lib/libx52/test_blink_shift.c b/lib/libx52/test_blink_shift.c deleted file mode 100644 index df54d6b..0000000 --- a/lib/libx52/test_blink_shift.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Saitek X52 Pro MFD & LED driver - * Test program for validating blink and shift functionality - * - * Copyright (C) 2020 Nirenjan Krishnan (nirenjan@nirenjan.org) - * - * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 - */ - -#include -#include -#include -#include "x52_common.h" -#include "test_common.h" -#include "x52_commands.h" - -typedef int (*blink_shift_fn)(libx52_device *, uint8_t); - -TEST_STRUCT ( - blink_shift_fn func; - uint8_t state; - struct ivpair data[2]; -) - -#define on 1 -#define off 0 - -#define x52_shift_indicator 0xfd -#define x52_shift_on 0x51 -#define x52_shift_off 0x50 - -#define x52_blink_indicator 0xb4 -#define x52_blink_on 0x51 -#define x52_blink_off 0x50 - -#define TEST(func, state) { #func "/" #state, libx52_set_ ## func, state, {{ x52_ ## func ## _indicator, x52_ ## func ## _ ## state}, {0, 0}}} - -TEST_CASES = { - TEST(blink, on), - TEST(blink, off), - TEST(shift, on), - TEST(shift, off), -}; - -TEST_FUNC() -{ - TEST_INIT(); - int rc = (*test.func)(dev, test.state); - - if (rc != LIBX52_SUCCESS) { - PRINT_FAIL(); - printf("# Expected success, got %d\n", rc); - return; - } - - TEST_VERIFY(test.data); -} - -TEST_MAIN() diff --git a/lib/libx52/test_common.c b/lib/libx52/test_common.c deleted file mode 100644 index 25440e4..0000000 --- a/lib/libx52/test_common.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Saitek X52 Pro MFD & LED driver - * Common functionality for test programs - * - * Copyright (C) 2020 Nirenjan Krishnan (nirenjan@nirenjan.org) - * - * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include "x52_common.h" -#include "test_common.h" - -#define MAX_DIAGS 32 -#define MAX_DIAG_SZ 256 -static int diag_count; -static char diagnostic[MAX_DIAGS][MAX_DIAG_SZ]; - -#define ADD_DIAG(fmt_str, ...) do { \ - if (diag_count < MAX_DIAGS) { \ - snprintf(diagnostic[diag_count], MAX_DIAG_SZ, fmt_str, ##__VA_ARGS__); \ - diag_count++; \ - } \ -} while(0) - -/* Test vendor command function */ -int x52_test_vendor_command(libx52_device *dev, uint16_t index, uint16_t value) -{ - struct x52_vendor_data *vdata = (struct x52_vendor_data *)dev->hdl; - struct ivpair data = {index, value}; - - if (vdata->written < MAX_SZ) { - vdata->data[vdata->written] = data; - vdata->written++; - } - - return LIBX52_SUCCESS; -} - -/* Check expected data */ -bool x52_test_assert_expected(libx52_device *dev, struct ivpair *data) -{ - int written = 0; - struct x52_vendor_data *vdata = (struct x52_vendor_data *)dev->hdl; - - while((data[written].index != 0 || data[written].value != 0) && written < vdata->written) { - if ((data[written].index != vdata->data[written].index) || - (data[written].value != vdata->data[written].value)) { - ADD_DIAG("Mismatched data at position %d:", written); - ADD_DIAG("\tExpected: {%04x, %04x}", data[written].index, data[written].value); - ADD_DIAG("\tObserved: {%04x, %04x}", vdata->data[written].index, vdata->data[written].value); - return false; - } - - written++; - } - - if (data[written].index != 0 || data[written].value != 0) { - ADD_DIAG("data written %d", written); - ADD_DIAG("Insufficient data written, got only %d, additional expected:", written); - while (data[written].index != 0 && data[written].value != 0) { - ADD_DIAG("\t%04x %04x", data[written].index, data[written].value); - written++; - } - return false; - } - - if (vdata->written > written) { - ADD_DIAG("More data written, expected only %d, got %d", written, vdata->written); - return false; - } - - return true; -} - -void x52_test_print_diagnostics(void) -{ - int i; - for (i = 0; i < diag_count; i++) { - printf("# %s\n", diagnostic[i]); - } -} - -static void _x52_test_print_data(struct ivpair *data) -{ - while (data->index != 0 || data->value != 0) { - printf("%04x/%04x ", data->index, data->value); - data++; - } - puts(""); -} - -void x52_test_print_observed_data(libx52_device *dev) -{ - struct x52_vendor_data *vdata = (struct x52_vendor_data *)dev->hdl; - printf("Observed: "); - _x52_test_print_data(vdata->data); -} - -void x52_test_print_expected_data(struct ivpair *data) -{ - printf("Expected: "); - _x52_test_print_data(data); -} - -/* - * Initialize libx52, close any device handles, create a dummy handle - * and override the vendor command function. - */ -libx52_device *x52_test_init(void) -{ - libx52_device *dev; - struct x52_vendor_data *vdata; - int rc; - - rc = libx52_init(&dev); - if (rc != LIBX52_SUCCESS) { - fputs(libx52_strerror(rc), stderr); - exit(1); - } - - (void)libx52_disconnect(dev); - - /* Allocate memory for vendor data */ - vdata = calloc(1, sizeof(*vdata)); - if (vdata == NULL) { - perror("vendor data calloc"); - libx52_exit(dev); - return NULL; - } - - /* Reset the diagnostics buffers */ - memset(diagnostic, 0, sizeof(diagnostic)); - diag_count = 0; - - /* We don't need the device handle in test code, repurpose it */ - dev->hdl = (libusb_device_handle *)vdata; - - /* Setup vendor command function */ - dev->vendor_cmd_fn = x52_test_vendor_command; - - return dev; -} - -void x52_test_cleanup(libx52_device *dev) -{ - free(dev->hdl); - dev->hdl = NULL; - libx52_exit(dev); -} diff --git a/lib/libx52/test_common.h b/lib/libx52/test_common.h deleted file mode 100644 index 1aaa1a2..0000000 --- a/lib/libx52/test_common.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Saitek X52 Pro MFD & LED driver - * Common functionality for test programs - * - * Copyright (C) 2020 Nirenjan Krishnan (nirenjan@nirenjan.org) - * - * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 - */ - -#ifndef _TEST_COMMON_H -#define _TEST_COMMON_H -#include -#include -#include "x52_common.h" - -/* ivpair is a pair of index and value fields that are passed to the - * test vendor command function. - */ -struct ivpair { - uint16_t index; - uint16_t value; -}; - -#define MAX_SZ 100 -struct x52_vendor_data { - int written; - struct ivpair data[MAX_SZ]; -}; - -/* - * Initialize libx52, close any device handles, create a dummy handle - * and override the vendor command function. - */ -libx52_device *x52_test_init(void); - -/* - * Check if expected data matches with written data. Terminate expected - * data with a pair of NULLs - */ -bool x52_test_assert_expected(libx52_device *dev, struct ivpair *data); - -/* Print diagnostics to screen */ -void x52_test_print_diagnostics(void); - -/* Cleanup test data */ -void x52_test_cleanup(libx52_device *dev); - -void x52_test_print_observed_data(libx52_device *dev); -void x52_test_print_expected_data(struct ivpair *data); - -#define PRINT_FAIL() printf("not ok %d %s\n", tc_id+1, test.test_case_id) -#define PRINT_PASS() printf("ok %d %s\n", tc_id+1, test.test_case_id) -#define TEST_STRUCT(...) struct test_case { \ - const char *test_case_id; \ - __VA_ARGS__ \ -}; - -#define TEST_CASES const struct test_case test_cases[] -#define TEST_FUNC() void run_test(int tc_id) -#define TEST_INIT() \ - struct libx52_device *dev = x52_test_init(); \ - struct test_case test = test_cases[tc_id]; - -#define TEST_VERIFY(data) do { \ - int test_rc; \ - test_rc = libx52_update(dev); \ - if (test_rc != LIBX52_SUCCESS) { \ - PRINT_FAIL(); \ - printf("# libx52_update failed, rc = %d\n", test_rc); \ - return; \ - } \ - \ - if (!x52_test_assert_expected(dev, data)) { \ - PRINT_FAIL(); \ - x52_test_print_diagnostics(); \ - x52_test_print_expected_data(data); \ - x52_test_print_observed_data(dev); \ - return; \ - } \ - \ - PRINT_PASS(); \ - x52_test_cleanup(dev); \ -} while(0) - -#define TEST_MAIN() int main() { \ - int i; \ - size_t tc_count = sizeof(test_cases) / sizeof(test_cases[0]); \ - printf("1..%lu\n", tc_count); \ - for (i = 0; i < tc_count; i++) { \ - run_test(i); \ - } \ -} - -#endif // !defined _TEST_COMMON_H diff --git a/lib/libx52/test_led.c b/lib/libx52/test_led.c deleted file mode 100644 index 16b9213..0000000 --- a/lib/libx52/test_led.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Saitek X52 Pro MFD & LED driver - * Test program for validating LED sets - * - * Copyright (C) 2020 Nirenjan Krishnan (nirenjan@nirenjan.org) - * - * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 - */ - -#include -#include -#include -#include "x52_common.h" -#include "test_common.h" -#include "x52_commands.h" - -TEST_STRUCT ( - libx52_led_id led_id; - libx52_led_state state; - int retval; - struct ivpair data[3]; -) - -#define X52_LED_CMD 0xb8 -#define UNSUPPORTED(led, state) { #led "/" #state " unsupported", LIBX52_LED_ ## led, LIBX52_LED_STATE_ ## state, LIBX52_ERROR_NOT_SUPPORTED} -#define OFF_MONO(led) { #led "/Off", LIBX52_LED_## led, LIBX52_LED_STATE_OFF, LIBX52_SUCCESS, {{X52_LED_CMD, ((LIBX52_LED_ ## led) << 8)}, {0, 0}}} -#define ON(led) { #led "/On", LIBX52_LED_## led, LIBX52_LED_STATE_ON, LIBX52_SUCCESS, {{X52_LED_CMD, ((LIBX52_LED_ ## led) << 8) | 1}, {0, 0}}} -#define OFF_COLOR(led) { #led "/Off", LIBX52_LED_## led, LIBX52_LED_STATE_OFF, LIBX52_SUCCESS, {{X52_LED_CMD, ((LIBX52_LED_ ## led + 0) << 8)}, {X52_LED_CMD, ((LIBX52_LED_ ## led + 1) << 8)}, {0, 0}}} -#define RED(led) { #led "/Red", LIBX52_LED_## led, LIBX52_LED_STATE_RED, LIBX52_SUCCESS, {{X52_LED_CMD, ((LIBX52_LED_ ## led + 0) << 8) | 1}, {X52_LED_CMD, ((LIBX52_LED_ ## led + 1) << 8) | 0}, {0, 0}}} -#define AMBER(led) { #led "/Amber", LIBX52_LED_## led, LIBX52_LED_STATE_AMBER, LIBX52_SUCCESS, {{X52_LED_CMD, ((LIBX52_LED_ ## led + 0) << 8) | 1}, {X52_LED_CMD, ((LIBX52_LED_ ## led + 1) << 8) | 1}, {0, 0}}} -#define GREEN(led) { #led "/Green", LIBX52_LED_## led, LIBX52_LED_STATE_GREEN, LIBX52_SUCCESS, {{X52_LED_CMD, ((LIBX52_LED_ ## led + 0) << 8) | 0}, {X52_LED_CMD, ((LIBX52_LED_ ## led + 1) << 8) | 1}, {0, 0}}} - -TEST_CASES = { - OFF_MONO(FIRE), - ON(FIRE), - UNSUPPORTED(FIRE, RED), - UNSUPPORTED(FIRE, AMBER), - UNSUPPORTED(FIRE, GREEN), - - OFF_COLOR(A), - UNSUPPORTED(A, ON), - RED(A), - AMBER(A), - GREEN(A), - - OFF_COLOR(B), - UNSUPPORTED(B, ON), - RED(B), - AMBER(B), - GREEN(B), - - OFF_COLOR(D), - UNSUPPORTED(D, ON), - RED(D), - AMBER(D), - GREEN(D), - - OFF_COLOR(E), - UNSUPPORTED(E, ON), - RED(E), - AMBER(E), - GREEN(E), - - OFF_COLOR(T1), - UNSUPPORTED(T1, ON), - RED(T1), - AMBER(T1), - GREEN(T1), - - OFF_COLOR(T2), - UNSUPPORTED(T2, ON), - RED(T2), - AMBER(T2), - GREEN(T2), - - OFF_COLOR(T3), - UNSUPPORTED(T3, ON), - RED(T3), - AMBER(T3), - GREEN(T3), - - OFF_COLOR(POV), - UNSUPPORTED(POV, ON), - RED(POV), - AMBER(POV), - GREEN(POV), - - OFF_COLOR(CLUTCH), - UNSUPPORTED(CLUTCH, ON), - RED(CLUTCH), - AMBER(CLUTCH), - GREEN(CLUTCH), - - OFF_MONO(THROTTLE), - ON(THROTTLE), - UNSUPPORTED(THROTTLE, RED), - UNSUPPORTED(THROTTLE, AMBER), - UNSUPPORTED(THROTTLE, GREEN), -}; - - -TEST_FUNC() -{ - TEST_INIT(); - - /* Set the X52Pro flag in dev->flags, otherwise libx52_set_led_state will - * always return not supported - */ - dev->flags = 1; - - int rc = libx52_set_led_state(dev, test.led_id, test.state); - - if (rc != test.retval) { - PRINT_FAIL(); - printf("# Expected retval %d, got %d\n", test.retval, rc); - return; - } - - TEST_VERIFY(test.data); -} - -TEST_MAIN() diff --git a/lib/libx52/test_offset.c b/lib/libx52/test_offset.c deleted file mode 100644 index 6d48193..0000000 --- a/lib/libx52/test_offset.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Saitek X52 Pro MFD & LED driver - * Test program for validating offset calculation - * - * Copyright (C) 2020 Nirenjan Krishnan (nirenjan@nirenjan.org) - * - * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 - */ - -#include -#include -#include -#include "x52_common.h" -#include "test_common.h" - -TEST_STRUCT ( - int offset_primary; - int offset_secondary; - libx52_clock_id clock_id; - uint16_t x52_clock; - uint16_t x52_offset; -) - -#define TEST(id, o1, o23, offs) {id, o1, o23, LIBX52_CLOCK_2, 0xc1, offs}, {id, o1, o23, LIBX52_CLOCK_3, 0xc2, offs} - -TEST_CASES = { - TEST("Etc/UTC+24|Etc/UTC-24", -1440, +1440, 0), - TEST("Etc/UTC-24|Etc/UTC+24", +1440, -1440, 0x0400), // Negative 0 - TEST("Honolulu|Auckland", -600, +720, 0x0478), // -2 hours - TEST("Auckland|Honolulu", +720, -600, 0x0078), // +2 hours - TEST("Etc/UTC+12|Etc/UTC-14", -720, +840, 0x078), // +2 hours - TEST("Etc/UTC-14|Etc/UTC+12", +840, -720, 0x478), // -2 hours - TEST("PDT|UTC", -420, 0, 0x1a4), // +7 hours - TEST("UTC|PDT", 0, -420, 0x5a4), // -7 hours - TEST("PST|UTC", -480, 0, 0x1e0), // +8 hours - TEST("UTC|PST", 0, -480, 0x5e0), // -8 hours - TEST("Etc/UTC+12|Etc/UTC-12", -720, +720, 0), - TEST("Etc/UTC-12|Etc/UTC+12", +720, -720, 0x0400), -}; - -TEST_FUNC() -{ - TEST_INIT(); - int rc; - struct ivpair data[2] = { 0 }; - - dev->timezone[LIBX52_CLOCK_1] = test.offset_primary; - rc = libx52_set_clock_timezone(dev, test.clock_id, test.offset_secondary); - if (rc != LIBX52_SUCCESS) { - PRINT_FAIL(); - printf("# set_clock_timezone failed, rc = %d\n", rc); - return; - } - - data[0].index = test.x52_clock; - data[0].value = test.x52_offset; - TEST_VERIFY(data); -} - -TEST_MAIN(); diff --git a/lib/libx52/x52_common.h b/lib/libx52/x52_common.h index 8916e4a..c3e8533 100644 --- a/lib/libx52/x52_common.h +++ b/lib/libx52/x52_common.h @@ -25,8 +25,6 @@ #define X52_MFD_LINES 3 #define X52_MFD_CLOCKS 3 -typedef int (*x52_vendor_command)(libx52_device *x52, uint16_t index, uint16_t value); - struct x52_mfd_line { uint8_t text[X52_MFD_LINE_SIZE]; uint8_t length; @@ -53,7 +51,6 @@ struct libx52_device { int timezone[X52_MFD_CLOCKS]; libx52_clock_format time_format[X52_MFD_CLOCKS]; - x52_vendor_command vendor_cmd_fn; }; /** Flag bits */ @@ -108,6 +105,5 @@ static inline uint32_t tst_bit(uint32_t *value, uint32_t bit) } int _x52_translate_libusb_error(enum libusb_error errcode); -int _x52_vendor_command(libx52_device *x52, uint16_t index, uint16_t value); #endif /* !defined X52JOY_COMMON_H */ diff --git a/lib/libx52/x52_control.c b/lib/libx52/x52_control.c index dc3f0ed..420cfc3 100644 --- a/lib/libx52/x52_control.c +++ b/lib/libx52/x52_control.c @@ -66,11 +66,18 @@ int _x52_translate_libusb_error(enum libusb_error errcode) }; } -int _x52_vendor_command(libx52_device *x52, uint16_t index, uint16_t value) +int libx52_vendor_command(libx52_device *x52, uint16_t index, uint16_t value) { int j; int rc = 0; + /* It is possible for the vendor command to be called when the joystick + * is not connected. Check for this and return an appropriate error. + */ + if (!x52->hdl) { + return LIBX52_ERROR_NO_DEVICE; + } + /* Allow retry in case of failure */ for (j = 0; j < 3; j++) { rc = libusb_control_transfer(x52->hdl, @@ -82,22 +89,6 @@ int _x52_vendor_command(libx52_device *x52, uint16_t index, uint16_t value) } } - return rc; -} - -int libx52_vendor_command(libx52_device *x52, uint16_t index, uint16_t value) -{ - int rc = 0; - - /* It is possible for the vendor command to be called when the joystick - * is not connected. Check for this and return an appropriate error. - */ - if (!x52->hdl || !x52->vendor_cmd_fn) { - return LIBX52_ERROR_NO_DEVICE; - } - - rc = (*(x52->vendor_cmd_fn))(x52, index, value); - /* Handle device removal */ if (rc == LIBUSB_ERROR_NO_DEVICE) { /* Physical device has likely been disconnected, disconnect the virtual diff --git a/lib/libx52/x52_core.c b/lib/libx52/x52_core.c index fe42c58..8a0470d 100644 --- a/lib/libx52/x52_core.c +++ b/lib/libx52/x52_core.c @@ -61,7 +61,6 @@ int libx52_disconnect(libx52_device *dev) libusb_close(dev->hdl); dev->hdl = NULL; dev->flags = 0; - dev->vendor_cmd_fn = NULL; } return LIBX52_SUCCESS; @@ -103,9 +102,6 @@ int libx52_connect(libx52_device *dev) dev->hdl = hdl; - /* Use default vendor command function */ - dev->vendor_cmd_fn = _x52_vendor_command; - if (libx52_device_is_x52pro(desc.idProduct)) { set_bit(&(dev->flags), X52_FLAG_IS_PRO); }