Edward O'Callaghan submitted this change.

View Change

Approvals: build bot (Jenkins): Verified Edward O'Callaghan: Looks good to me, approved
tests: Add init-shutdown test for raiden_debug_spi

This patch adds a test for raiden_debug_spi and lots of libusb wraps.

libusb.h becomes required for tests to build and run, since new tests
are using libusb structs in depth and opaque symbols not sufficient
anymore.

BUG=b:181803212
TEST=builds and ninja test

Change-Id: I880a8637ab02de179df9169c1898230bce4dc1c7
Signed-off-by: Anastasia Klimchuk <aklm@chromium.org>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/57918
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
---
M tests/init_shutdown.c
M tests/io_mock.h
M tests/libusb_wraps.c
M tests/meson.build
M tests/tests.c
M tests/tests.h
6 files changed, 208 insertions(+), 5 deletions(-)

diff --git a/tests/init_shutdown.c b/tests/init_shutdown.c
index e64e58c..2a8d6f5 100644
--- a/tests/init_shutdown.c
+++ b/tests/init_shutdown.c
@@ -54,6 +54,101 @@
#endif
}

+static ssize_t raiden_debug_libusb_get_device_list(void *state, libusb_context *ctx, libusb_device ***list)
+{
+ *list = calloc(1, sizeof(**list));
+
+ /*
+ * libusb_device is opaque type, it is tossed around between libusb functions but always
+ * stays opaque to the caller.
+ * Given that all libusb functions are mocked in tests, and raiden_debug test is mocking
+ * only one device, we don't need to initialise libusb_device.
+ */
+ return 1;
+}
+
+static void raiden_debug_libusb_free_device_list(void *state, libusb_device **list, int unref_devices)
+{
+ free(list);
+}
+
+static int raiden_debug_libusb_get_device_descriptor(
+ void *state, libusb_device *dev, struct libusb_device_descriptor *desc)
+{
+ desc->idVendor = 0x18D1; /* GOOGLE_VID */
+ desc->idProduct = 0;
+ desc->bNumConfigurations = 1;
+
+ return 0;
+}
+
+static int raiden_debug_libusb_get_config_descriptor(
+ void *state, libusb_device *dev, uint8_t config_index, struct libusb_config_descriptor **config)
+{
+ *config = calloc(1, sizeof(**config));
+
+ struct libusb_endpoint_descriptor *tmp_endpoint = calloc(2, sizeof(*tmp_endpoint));
+ struct libusb_interface_descriptor *tmp_interface_desc = calloc(1, sizeof(*tmp_interface_desc));
+ struct libusb_interface *tmp_interface = calloc(1, sizeof(*tmp_interface));
+
+ /* in endpoint */
+ tmp_endpoint[0].bEndpointAddress = 0x80;
+ tmp_endpoint[0].bmAttributes = 0x2;
+ /* out endpoint */
+ tmp_endpoint[1].bEndpointAddress = 0x0;
+ tmp_endpoint[1].bmAttributes = 0x2;
+
+ tmp_interface_desc->bInterfaceClass = 0xff; /* LIBUSB_CLASS_VENDOR_SPEC */
+ tmp_interface_desc->bInterfaceSubClass = 0x51; /* GOOGLE_RAIDEN_SPI_SUBCLASS */
+ tmp_interface_desc->bInterfaceProtocol = 0x01; /* GOOGLE_RAIDEN_SPI_PROTOCOL_V1 */
+ tmp_interface_desc->bNumEndpoints = 2; /* in_endpoint and out_endpoint */
+ tmp_interface_desc->endpoint = tmp_endpoint;
+
+ tmp_interface->num_altsetting = 1;
+ tmp_interface->altsetting = tmp_interface_desc;
+
+ (*config)->bConfigurationValue = 0;
+ (*config)->bNumInterfaces = 1;
+ (*config)->interface = tmp_interface;
+
+ return 0;
+}
+
+static void raiden_debug_libusb_free_config_descriptor(void *state, struct libusb_config_descriptor *config)
+{
+ free((void *)config->interface->altsetting->endpoint);
+ free((void *)config->interface->altsetting);
+ free((void *)config->interface);
+ free(config);
+}
+
+void raiden_debug_init_and_shutdown_test_success(void **state)
+{
+#if CONFIG_RAIDEN_DEBUG_SPI == 1
+ const struct io_mock raiden_debug_io = {
+ .libusb_get_device_list = raiden_debug_libusb_get_device_list,
+ .libusb_free_device_list = raiden_debug_libusb_free_device_list,
+ .libusb_get_device_descriptor = raiden_debug_libusb_get_device_descriptor,
+ .libusb_get_config_descriptor = raiden_debug_libusb_get_config_descriptor,
+ .libusb_free_config_descriptor = raiden_debug_libusb_free_config_descriptor,
+ };
+
+ /*
+ * 12 is the length of programmer param string for 3-digit address.
+ * Address can be max 3-digit because it needs to fit into uint8_t.
+ */
+ char raiden_debug_param[12];
+ snprintf(raiden_debug_param, 12, "address=%d", USB_DEVICE_ADDRESS);
+
+ io_mock_register(&raiden_debug_io);
+
+ run_lifecycle(state, &programmer_raiden_debug_spi, raiden_debug_param);
+
+ io_mock_register(NULL);
+#else
+ skip();
+#endif
+}

int dediprog_libusb_init(void *state, libusb_context **ctx)
{
diff --git a/tests/io_mock.h b/tests/io_mock.h
index 0bee6ca..854ddd9 100644
--- a/tests/io_mock.h
+++ b/tests/io_mock.h
@@ -34,11 +34,14 @@
/* Required for `FILE *` */
#include <stdio.h>

-/* Define libusb symbols to avoid dependency on libusb.h */
-struct libusb_device_handle;
-typedef struct libusb_device_handle libusb_device_handle;
-struct libusb_context;
-typedef struct libusb_context libusb_context;
+/*
+ * Explicitly including the header because some tests are using libusb structs
+ * in depth, opaque symbols are not sufficient.
+ */
+#include <libusb.h>
+
+/* Address value needs fit into uint8_t. */
+#define USB_DEVICE_ADDRESS 19

/* Define struct pci_dev to avoid dependency on pci.h */
struct pci_dev {
@@ -80,6 +83,14 @@
unsigned char *data,
uint16_t wLength,
unsigned int timeout);
+ ssize_t (*libusb_get_device_list)(void *state, libusb_context *, libusb_device ***list);
+ void (*libusb_free_device_list)(void *state, libusb_device **list, int unref_devices);
+ int (*libusb_get_device_descriptor)(void *state, libusb_device *, struct libusb_device_descriptor *);
+ int (*libusb_get_config_descriptor)(void *state,
+ libusb_device *,
+ uint8_t config_index,
+ struct libusb_config_descriptor **);
+ void (*libusb_free_config_descriptor)(void *state, struct libusb_config_descriptor *);

/* POSIX File I/O */
int (*open)(void *state, const char *pathname, int flags);
diff --git a/tests/libusb_wraps.c b/tests/libusb_wraps.c
index 978108e..8f9e243 100644
--- a/tests/libusb_wraps.c
+++ b/tests/libusb_wraps.c
@@ -13,6 +13,8 @@
* GNU General Public License for more details.
*/

+#include <stdlib.h>
+
#include <include/test.h>
#include "io_mock.h"

@@ -31,6 +33,76 @@
return 0;
}

+int __wrap_libusb_open(libusb_device *dev, libusb_device_handle **devh)
+{
+ LOG_ME;
+ return 0;
+}
+
+int __wrap_libusb_set_auto_detach_kernel_driver(libusb_device_handle *devh, int enable)
+{
+ LOG_ME;
+ return 0;
+}
+
+ssize_t __wrap_libusb_get_device_list(libusb_context *ctx, libusb_device ***list)
+{
+ LOG_ME;
+ if (get_io() && get_io()->libusb_get_device_list)
+ return get_io()->libusb_get_device_list(get_io()->state, ctx, list);
+ return 0;
+}
+
+void __wrap_libusb_free_device_list(libusb_device **list, int unref_devices)
+{
+ LOG_ME;
+ if (get_io() && get_io()->libusb_free_device_list)
+ get_io()->libusb_free_device_list(get_io()->state, list, unref_devices);
+}
+
+uint8_t __wrap_libusb_get_bus_number(libusb_device *dev)
+{
+ LOG_ME;
+ return 0;
+}
+
+uint8_t __wrap_libusb_get_device_address(libusb_device *dev)
+{
+ LOG_ME;
+ return USB_DEVICE_ADDRESS;
+}
+
+int __wrap_libusb_get_device_descriptor(libusb_device *dev, struct libusb_device_descriptor *desc)
+{
+ LOG_ME;
+ if (get_io() && get_io()->libusb_get_device_descriptor)
+ return get_io()->libusb_get_device_descriptor(get_io()->state, dev, desc);
+ return 0;
+}
+
+int __wrap_libusb_get_config_descriptor(
+ libusb_device *dev, uint8_t config_index, struct libusb_config_descriptor **config)
+{
+ LOG_ME;
+ if (get_io() && get_io()->libusb_get_config_descriptor)
+ return get_io()->libusb_get_config_descriptor(get_io()->state, dev, config_index, config);
+ return 0;
+}
+
+void __wrap_libusb_free_config_descriptor(struct libusb_config_descriptor *config)
+{
+ LOG_ME;
+ if (get_io() && get_io()->libusb_free_config_descriptor)
+ return get_io()->libusb_free_config_descriptor(get_io()->state, config);
+ return;
+}
+
+int __wrap_libusb_get_configuration(libusb_device_handle *devh, int *config)
+{
+ LOG_ME;
+ return 0;
+}
+
int __wrap_libusb_set_configuration(libusb_device_handle *devh, int config)
{
LOG_ME;
@@ -65,6 +137,17 @@
LOG_ME;
}

+libusb_device *__wrap_libusb_ref_device(libusb_device *dev)
+{
+ LOG_ME;
+ return NULL;
+}
+
+void __wrap_libusb_unref_device(libusb_device *dev)
+{
+ LOG_ME;
+}
+
void __wrap_libusb_exit(libusb_context *ctx)
{
LOG_ME;
diff --git a/tests/meson.build b/tests/meson.build
index 415ce13..5bb6ac9 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -70,10 +70,22 @@
'-Wl,--wrap=test_inl',
'-Wl,--wrap=usb_dev_get_by_vid_pid_number',
'-Wl,--wrap=libusb_init',
+ '-Wl,--wrap=libusb_open',
+ '-Wl,--wrap=libusb_set_auto_detach_kernel_driver',
+ '-Wl,--wrap=libusb_get_device_list',
+ '-Wl,--wrap=libusb_free_device_list',
+ '-Wl,--wrap=libusb_get_bus_number',
+ '-Wl,--wrap=libusb_get_device_address',
+ '-Wl,--wrap=libusb_get_device_descriptor',
+ '-Wl,--wrap=libusb_get_config_descriptor',
+ '-Wl,--wrap=libusb_free_config_descriptor',
+ '-Wl,--wrap=libusb_get_configuration',
'-Wl,--wrap=libusb_set_configuration',
'-Wl,--wrap=libusb_claim_interface',
'-Wl,--wrap=libusb_control_transfer',
'-Wl,--wrap=libusb_release_interface',
+ '-Wl,--wrap=libusb_ref_device',
+ '-Wl,--wrap=libusb_unref_device',
'-Wl,--wrap=libusb_close',
'-Wl,--wrap=libusb_exit',
'-Wl,--gc-sections',
diff --git a/tests/tests.c b/tests/tests.c
index f2547ff..a4a312e 100644
--- a/tests/tests.c
+++ b/tests/tests.c
@@ -351,6 +351,7 @@
const struct CMUnitTest init_shutdown_tests[] = {
cmocka_unit_test(dummy_init_and_shutdown_test_success),
cmocka_unit_test(nicrealtek_init_and_shutdown_test_success),
+ cmocka_unit_test(raiden_debug_init_and_shutdown_test_success),
cmocka_unit_test(dediprog_init_and_shutdown_test_success),
cmocka_unit_test(linux_mtd_init_and_shutdown_test_success),
cmocka_unit_test(linux_spi_init_and_shutdown_test_success),
diff --git a/tests/tests.h b/tests/tests.h
index 732920a..16974af 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -43,6 +43,7 @@
/* init_shutdown.c */
void dummy_init_and_shutdown_test_success(void **state);
void nicrealtek_init_and_shutdown_test_success(void **state);
+void raiden_debug_init_and_shutdown_test_success(void **state);
void dediprog_init_and_shutdown_test_success(void **state);
void linux_mtd_init_and_shutdown_test_success(void **state);
void linux_spi_init_and_shutdown_test_success(void **state);

8 is the latest approved patch-set. No files were changed between the latest approved patch-set and the submitted one.

To view, visit change 57918. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: I880a8637ab02de179df9169c1898230bce4dc1c7
Gerrit-Change-Number: 57918
Gerrit-PatchSet: 10
Gerrit-Owner: Anastasia Klimchuk <aklm@chromium.org>
Gerrit-Reviewer: Angel Pons <th3fanbus@gmail.com>
Gerrit-Reviewer: Edward O'Callaghan <quasisec@chromium.org>
Gerrit-Reviewer: Nico Huber <nico.h@gmx.de>
Gerrit-Reviewer: Thomas Heijligen <src@posteo.de>
Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org>
Gerrit-CC: Paul Menzel <paulepanter@mailbox.org>
Gerrit-MessageType: merged