From 937027f93da5de78ccdcc22d9d93c67a44cf42fe Mon Sep 17 00:00:00 2001 From: "peter.marcisovsky" Date: Wed, 6 Nov 2024 15:11:58 +0100 Subject: [PATCH 1/3] feat(cdc_acm): Mocked device open/close - Opening and closing mocked USB devices - Interaction with mocked USB devices --- .../usb_host_cdc_acm/host_test/CMakeLists.txt | 1 + .../host_test/main/common_test_fixtures.cpp | 401 ++++++++++++++++++ .../host_test/main/common_test_fixtures.hpp | 148 +++++++ .../main/test_device_interaction.cpp | 188 ++++++++ .../host_test/main/test_opening_device.cpp | 255 +++++++++++ .../host_test/main/test_unit_public_api.cpp | 70 ++- 6 files changed, 1057 insertions(+), 6 deletions(-) create mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.cpp create mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.hpp create mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/main/test_device_interaction.cpp create mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/main/test_opening_device.cpp diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/CMakeLists.txt b/host/class/cdc/usb_host_cdc_acm/host_test/CMakeLists.txt index 460a5156..ffb1e583 100644 --- a/host/class/cdc/usb_host_cdc_acm/host_test/CMakeLists.txt +++ b/host/class/cdc/usb_host_cdc_acm/host_test/CMakeLists.txt @@ -8,4 +8,5 @@ list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/" ) +add_definitions("-DCMOCK_MEM_DYNAMIC") project(host_test_usb_cdc) diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.cpp new file mode 100644 index 00000000..b64fec75 --- /dev/null +++ b/host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.cpp @@ -0,0 +1,401 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "cdc_descriptors.hpp" +#include "usb/cdc_acm_host.h" +#include "mock_add_usb_device.h" +#include "common_test_fixtures.hpp" +#include "esp_system.h" +#include "cdc_host_descriptor_parsing.h" + +extern "C" { +#include "Mockusb_host.h" + +#include "Mockqueue.h" +#include "Mocktask.h" +#include "Mockidf_additions.h" +#include "Mockportmacro.h" +#include "Mockevent_groups.h" +} + +mock_cdc_acm_obj_t *p_mock_cdc_acm_obj = nullptr; +mock_cdc_dev_t *p_mock_cdc_dev = nullptr; + +/** + * @brief Create CDC device object + * + * @param[in] dev_address Device address + * @param[in] interface_idx Interface index to be used + * @param[in] dev_config CDC-ACM Host device config struct + * + * @return + * - ESP_OK: Device created successfully + * - ESP_ERR_NO_MEM: Not enough memory + */ +static esp_err_t _create_cdc_dev(uint8_t dev_address, uint8_t interface_idx, const cdc_acm_host_device_config_t *dev_config) +{ + mock_cdc_dev_t *mock_cdc_dev = (mock_cdc_dev_t *)calloc(1, sizeof(mock_cdc_dev_t)); + if (mock_cdc_dev == nullptr) { + return ESP_ERR_NO_MEM; + } + + int notif_xfer, data_in_xfer, data_out_xfer; + const usb_config_desc_t *config_desc; + const usb_device_desc_t *device_desc; + cdc_parsed_info_t cdc_info; + int out_mux, out_sem, ctrl_mux, ctrl_sem; + usb_host_mock_get_config_descriptor_by_address(dev_address, &config_desc); + usb_host_mock_get_device_descriptor_by_address(dev_address, &device_desc); + cdc_parse_interface_descriptor(device_desc, config_desc, interface_idx, &cdc_info); + + // Get interface descriptors + mock_cdc_dev->data.intf_desc = cdc_info.data_intf; + mock_cdc_dev->notif.intf_desc = cdc_info.notif_intf; + // Get IN and OUT endpoints addresses + mock_cdc_dev->data.in_bEndpointAddress = cdc_info.in_ep->bEndpointAddress; + mock_cdc_dev->data.out_bEndpointAddress = cdc_info.out_ep->bEndpointAddress; + + // Get notification endpoint address and check if notification transfer is allocated (if notif. EP exists) + if (cdc_info.notif_ep) { + mock_cdc_dev->notif.bEndpointAddress = cdc_info.notif_ep->bEndpointAddress; + mock_cdc_dev->notif.xfer = reinterpret_cast(¬if_xfer); + } else { + mock_cdc_dev->notif.bEndpointAddress = 0; + mock_cdc_dev->notif.xfer = nullptr; + } + + // Check, if IN data transfer is allocated + if (dev_config->in_buffer_size) { + mock_cdc_dev->data.in_xfer = reinterpret_cast(&data_in_xfer); + } else { + mock_cdc_dev->data.in_xfer = nullptr; + } + + // Check if OUT data transfer is allocated + if (dev_config->out_buffer_size) { + mock_cdc_dev->data.out_xfer = reinterpret_cast(&data_out_xfer); + mock_cdc_dev->data.out_mux = reinterpret_cast(&out_mux); + mock_cdc_dev->data.out_sem = reinterpret_cast(&out_sem); + } else { + mock_cdc_dev->data.out_xfer = nullptr; + mock_cdc_dev->data.out_mux = nullptr; + mock_cdc_dev->data.out_sem = nullptr; + } + + mock_cdc_dev->ctrl_mux = reinterpret_cast(&ctrl_mux); + mock_cdc_dev->ctrl_sem = reinterpret_cast(&ctrl_sem); + + p_mock_cdc_dev = mock_cdc_dev; + return ESP_OK; +} + +/** + * @brief free space allocated for p_mock_cdc_dev + */ +static void _delete_cdc_dev(void) +{ + free(p_mock_cdc_dev); + p_mock_cdc_dev = nullptr; +} + +/** + * @brief Reset endpoint halt -> flush -> clear + * + * @param ep_address[in] Endpoint address to be reset + */ +static void _mock_cdc_acm_reset_transfer_endpoint(uint8_t ep_address) +{ + // Expect correct ep_address for all (halt, flush, clear) + usb_host_endpoint_halt_ExpectAndReturn(nullptr, ep_address, ESP_OK); + usb_host_endpoint_halt_IgnoreArg_dev_hdl(); + + usb_host_endpoint_flush_ExpectAndReturn(nullptr, ep_address, ESP_OK); + usb_host_endpoint_flush_IgnoreArg_dev_hdl(); + + usb_host_endpoint_clear_ExpectAndReturn(nullptr, ep_address, ESP_OK); + usb_host_endpoint_clear_IgnoreArg_dev_hdl(); +} + +esp_err_t mock_cdc_acm_host_install(const cdc_acm_host_driver_config_t *driver_config) +{ + vPortEnterCritical_Ignore(); // Ignore expecting vPortEnterCritical() + vPortExitCritical_Ignore(); // Ignore expecting vPortExitCritical() + + if (p_mock_cdc_acm_obj != nullptr) { + // CDC-ACM already installed + return ESP_ERR_INVALID_STATE; + } + + mock_cdc_acm_obj_t *mock_cdc_acm_obj = (mock_cdc_acm_obj_t *)calloc(1, sizeof(mock_cdc_acm_obj_t)); + if (mock_cdc_acm_obj == nullptr) { + return ESP_ERR_NO_MEM; + } + + int task_handle_ptr; + // Ensure task_handle is non nullptr, as it is used in ReturnThruPtr type of CMock function + TaskHandle_t task_handle = reinterpret_cast(&task_handle_ptr); + usb_host_client_handle_t client_handle = reinterpret_cast(&mock_cdc_acm_obj->cdc_acm_client_hdl); + // Create an EventGroup, return event group handle, so the EventGroup is created successfully + xEventGroupCreate_ExpectAndReturn(reinterpret_cast(&mock_cdc_acm_obj->event_group)); + // We should be calling xSemaphoreCreteMutex_ExpectAnyArgsAndRetrun instead of xQueueCreateMutex_ExpectAnyArgsAndReturn + // Because of missing Freertos Mocks + // Create a semaphore, return the semaphore handle (Queue Handle in this scenario), so the semaphore is created successfully + xQueueCreateMutex_ExpectAnyArgsAndReturn(reinterpret_cast(&mock_cdc_acm_obj->open_close_mutex)); + // Create a task, return pdTRUE, so the task is created successfully + xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdTRUE); + // Return task handle by pointer + xTaskCreatePinnedToCore_ReturnThruPtr_pxCreatedTask(&task_handle); + + // Call mocked function from USB Host + // return ESP_OK, so the client si registered successfully + usb_host_client_register_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_client_register_ReturnThruPtr_client_hdl_ret(&client_handle); + + // Resume the task + vTaskResume_Expect(task_handle); + + p_mock_cdc_acm_obj = mock_cdc_acm_obj; + + // Call the real function cdc_acm_host_install() + return cdc_acm_host_install(driver_config); +} + +esp_err_t mock_cdc_acm_host_uninstall(void) +{ + vPortEnterCritical_Ignore(); // Ignore expecting vPortEnterCritical() + vPortExitCritical_Ignore(); // Ignore expecting vPortExitCritical() + + xQueueSemaphoreTake_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->open_close_mutex), portMAX_DELAY, pdTRUE); + + // Signal to CDC task to stop, unblock it and wait for its deletion + xEventGroupSetBits_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->event_group), BIT0, pdTRUE); + + // Call mocked function from USB Host + // return ESP_OK, so the client si unblocked successfully + usb_host_client_unblock_ExpectAnyArgsAndReturn(ESP_OK); + xEventGroupWaitBits_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->event_group), BIT1, pdFALSE, pdFALSE, pdMS_TO_TICKS(100), pdTRUE); + + // Free remaining resources + vEventGroupDelete_Expect(reinterpret_cast(&p_mock_cdc_acm_obj->event_group)); + xQueueGenericSend_ExpectAnyArgsAndReturn(pdTRUE); + vQueueDelete_Expect(reinterpret_cast(&p_mock_cdc_acm_obj->open_close_mutex)); + + free(p_mock_cdc_acm_obj); + p_mock_cdc_acm_obj = nullptr; + _delete_cdc_dev(); + + // Call the real function, cdc_acm_host_uninstall() + return cdc_acm_host_uninstall(); +} + +esp_err_t mock_cdc_acm_host_open(uint8_t dev_address, uint16_t vid, uint16_t pid, uint8_t interface_idx, const cdc_acm_host_device_config_t *dev_config, cdc_acm_dev_hdl_t *cdc_hdl_ret) +{ + vPortEnterCritical_Ignore(); // Ignore expecting vPortEnterCritical() + vPortExitCritical_Ignore(); // Ignore expecting vPortExitCritical() + + esp_err_t ret_create_dev = _create_cdc_dev(dev_address, interface_idx, dev_config); + if (ret_create_dev != ESP_OK) { + return ret_create_dev; // ESP_ERR_NO_MEM + } + + xQueueSemaphoreTake_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->open_close_mutex), portMAX_DELAY, pdTRUE); + vTaskSetTimeOutState_ExpectAnyArgs(); + + // Device opening + usb_host_device_addr_list_fill_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_device_addr_list_fill_AddCallback(usb_host_device_addr_list_fill_callback); + + // We are expecting usb_host_device_open, usb_host_get_device_descriptor usb_host_device_close + // to be called at least mocked_devs_count times + const int mocked_devs_count = usb_host_mock_get_devs_count(); // Get number of mocked USB devices in mocked device list + for (int i = 0; i < mocked_devs_count; i++) { + usb_host_device_open_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_device_close_ExpectAnyArgsAndReturn(ESP_OK); + } + + usb_host_device_open_AddCallback(usb_host_device_open_callback); + usb_host_get_device_descriptor_AddCallback(usb_host_get_device_descriptor_callback); + usb_host_device_close_AddCallback(usb_host_device_close_callback); + + // We have found the device by specified PID VID + + // Get Device and Configuration descriptors of the correct device + usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_active_config_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_active_config_descriptor_AddCallback(usb_host_get_active_config_descriptor_callback); + + // Setup control transfer + usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); + // Semaphore: cdc_dev->ctrl_transfer->context = xSemaphoreCreateBinary(); + xQueueGenericCreate_ExpectAnyArgsAndReturn(p_mock_cdc_dev->ctrl_sem); + // Mutex: cdc_dev->ctrl_mux = xSemaphoreCreateMutex(); + xQueueCreateMutex_ExpectAnyArgsAndReturn(p_mock_cdc_dev->ctrl_mux); + + // Setup Notif transfer + if (p_mock_cdc_dev->notif.xfer) { + usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); + } + + // Setup IN data transfer + if (dev_config->in_buffer_size) { + usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); + } + + // Setup OUT bulk transfer + if (dev_config->out_buffer_size) { + usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); + // Semaphore: cdc_dev->data.out_xfer->context = xSemaphoreCreateBinary(); + xQueueGenericCreate_ExpectAnyArgsAndReturn(p_mock_cdc_dev->data.out_sem); + // Mutex: cdc_dev->data.out_mux = xSemaphoreCreateMutex(); + xQueueCreateMutex_ExpectAnyArgsAndReturn(p_mock_cdc_dev->data.out_mux); + } + + // Register callback + usb_host_transfer_alloc_AddCallback(usb_host_transfer_alloc_callback); + + // Call cdc_acm_start + + // Claim data interface + // Make sure that the interface_idx has been claimed + usb_host_interface_claim_ExpectAndReturn(nullptr, nullptr, interface_idx, 0, ESP_OK); + usb_host_interface_claim_IgnoreArg_client_hdl(); // Ignore all function parameters, except interface_number + usb_host_interface_claim_IgnoreArg_dev_hdl(); + usb_host_interface_claim_IgnoreArg_bAlternateSetting(); + usb_host_transfer_submit_ExpectAnyArgsAndReturn(ESP_OK); + + // Claim notification interface (if supported) + if (p_mock_cdc_dev->notif.xfer) { + usb_host_interface_claim_ExpectAndReturn(nullptr, nullptr, interface_idx, 0, ESP_OK); + usb_host_interface_claim_IgnoreArg_client_hdl(); // Ignore all function parameters, except interface_number + usb_host_interface_claim_IgnoreArg_dev_hdl(); + usb_host_interface_claim_IgnoreArg_bAlternateSetting(); + usb_host_transfer_submit_ExpectAnyArgsAndReturn(ESP_OK); + } + + xQueueGenericSend_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->open_close_mutex), nullptr, 0, 0, pdTRUE); + xQueueGenericSend_IgnoreArg_pvItemToQueue(); + xQueueGenericSend_IgnoreArg_xCopyPosition(); + xQueueGenericSend_IgnoreArg_xTicksToWait(); + + // Call the real function cdc_acm_host_open + // Expect ESP_OK and dev_hdl non nullptr + esp_err_t ret = cdc_acm_host_open(vid, pid, interface_idx, dev_config, cdc_hdl_ret); + + // If the cdc_acm_host_open() fails, delete the created cdc_device + if (ret != ESP_OK) { + _delete_cdc_dev(); + } + return ret; +} + +esp_err_t mock_cdc_acm_host_close(cdc_acm_dev_hdl_t *cdc_hdl, uint8_t interface_number) +{ + vPortEnterCritical_Ignore(); // Ignore vPortEnterCritical() during this test case + vPortExitCritical_Ignore(); // Ignore vPortExitCritical() during this test case + + xQueueSemaphoreTake_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->open_close_mutex), portMAX_DELAY, pdTRUE); + + // Cancel pooling of IN endpoint -> halt, flush, clear + _mock_cdc_acm_reset_transfer_endpoint(p_mock_cdc_dev->data.in_bEndpointAddress); + + // Cancel pooling of Notification endpoint -> halt, flush, clear + if (p_mock_cdc_dev->notif.xfer) { + _mock_cdc_acm_reset_transfer_endpoint(p_mock_cdc_dev->notif.bEndpointAddress); + } + + // Release data interface + usb_host_interface_release_ExpectAndReturn(nullptr, nullptr, interface_number, ESP_OK); + usb_host_interface_release_IgnoreArg_client_hdl(); // Ignore all function parameters, except interface_number + usb_host_interface_release_IgnoreArg_dev_hdl(); + + + // Free notif transfer + if (p_mock_cdc_dev->notif.xfer) { + usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); + p_mock_cdc_dev->notif.xfer = nullptr; + } + + // Free in transfer + if (p_mock_cdc_dev->data.in_xfer) { + usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); + p_mock_cdc_dev->data.in_xfer = nullptr; + } + + // Free out transfer + if (p_mock_cdc_dev->data.out_xfer) { + usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); + vQueueDelete_Expect(p_mock_cdc_dev->data.out_sem); + vQueueDelete_Expect(p_mock_cdc_dev->data.out_mux); + p_mock_cdc_dev->data.out_xfer = nullptr; + } + + // Call cdc_acm_device_remove + // Free ctrl transfer + usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); + vQueueDelete_Expect(p_mock_cdc_dev->ctrl_sem); + vQueueDelete_Expect(p_mock_cdc_dev->ctrl_mux); + + usb_host_transfer_free_AddCallback(usb_host_transfer_free_callback); + + usb_host_device_close_ExpectAnyArgsAndReturn(ESP_OK); + + xQueueGenericSend_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->open_close_mutex), nullptr, 0, 0, pdTRUE); + xQueueGenericSend_IgnoreArg_pvItemToQueue(); + xQueueGenericSend_IgnoreArg_xCopyPosition(); + xQueueGenericSend_IgnoreArg_xTicksToWait(); + + // Call the real function cdc_acm_host_close + return cdc_acm_host_close(*cdc_hdl); +} + +esp_err_t mock_cdc_acm_host_data_tx_blocking(cdc_acm_dev_hdl_t cdc_hdl, const uint8_t *data, size_t data_len, uint32_t timeout_ms, mock_usb_transfer_response_t transfer_response) +{ + vPortEnterCritical_Ignore(); // Ignore vPortEnterCritical() during this test case + vPortExitCritical_Ignore(); // Ignore vPortExitCritical() during this test case + + xQueueSemaphoreTake_ExpectAndReturn(p_mock_cdc_dev->data.out_mux, pdMS_TO_TICKS(timeout_ms), pdTRUE); + xQueueSemaphoreTake_ExpectAndReturn(p_mock_cdc_dev->data.out_sem, 0, pdTRUE); + usb_host_transfer_submit_ExpectAnyArgsAndReturn(ESP_OK); + + switch (transfer_response) { + case MOCK_USB_TRANSFER_SUCCESS: { + // Make the submitted transfer to pass + usb_host_transfer_submit_AddCallback(usb_host_transfer_submit_success_callback); + xQueueSemaphoreTake_ExpectAndReturn(p_mock_cdc_dev->data.out_sem, pdMS_TO_TICKS(timeout_ms), pdTRUE); + break; + } + case MOCK_USB_TRANSFER_ERROR: { + // Make the submitted transfer to fail + usb_host_transfer_submit_AddCallback(usb_host_transfer_submit_fail_callback); + xQueueSemaphoreTake_ExpectAndReturn(p_mock_cdc_dev->data.out_sem, pdMS_TO_TICKS(timeout_ms), pdTRUE); + break; + } + case MOCK_USB_TRANSFER_TIMEOUT: { + // Make the submitted transfer to be timed out + usb_host_transfer_submit_AddCallback(usb_host_transfer_submit_success_callback); + xQueueSemaphoreTake_ExpectAndReturn(p_mock_cdc_dev->data.out_sem, pdMS_TO_TICKS(timeout_ms), pdFALSE); + + // Reset out endpoint + _mock_cdc_acm_reset_transfer_endpoint(p_mock_cdc_dev->data.out_bEndpointAddress); + break; + } + default: + break; + } + + xQueueGenericSend_ExpectAndReturn(p_mock_cdc_dev->data.out_mux, 0, 0, 0, pdTRUE); + xQueueGenericSend_IgnoreArg_pvItemToQueue(); + xQueueGenericSend_IgnoreArg_xCopyPosition(); + xQueueGenericSend_IgnoreArg_xTicksToWait(); + + // Call the real function cdc_acm_host_data_tx_blocking() + return cdc_acm_host_data_tx_blocking(cdc_hdl, data, data_len, timeout_ms); +} diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.hpp b/host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.hpp new file mode 100644 index 00000000..efef54ac --- /dev/null +++ b/host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.hpp @@ -0,0 +1,148 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_err.h" +#include "freertos/queue.h" + +#pragma once + +/** + * @brief CDC-ACM mocked driver object + * + * Variation of cdc_acm_obj_t *p_cdc_acm_obj; but for host tests + */ +typedef struct { + int open_close_mutex; + int cdc_acm_client_hdl; + int event_group; +} mock_cdc_acm_obj_t; + +/** + * @brief CDC-ACM device + * + * Variation of cdc_dev_t but for host tests + */ +typedef struct { + struct { + usb_transfer_t *out_xfer; + usb_transfer_t *in_xfer; + const usb_intf_desc_t *intf_desc; + QueueHandle_t out_mux; // This should be SemaphoreHandle_t, but freertos mock is not correct + QueueHandle_t out_sem; // cdc_dev->data.out_xfer->context = xSemaphoreCreateBinary(); + uint8_t in_bEndpointAddress; + uint8_t out_bEndpointAddress; + } data; + struct { + usb_transfer_t *xfer; + const usb_intf_desc_t *intf_desc; + uint8_t bEndpointAddress; + } notif; + usb_transfer_t *ctr_transfer; + QueueHandle_t ctrl_mux; // This should be SemaphoreHandle_t, but freertos mock is not correct + QueueHandle_t ctrl_sem; // cdc_dev->ctrl_transfer->context = xSemaphoreCreateBinary(); +} mock_cdc_dev_t; + +/** + * @brief Intended transfer response + * + * It can be defined, how the is submitted, we can successfully submit a transfer, or we can induce some transfer errors + */ +typedef enum { + MOCK_USB_TRANSFER_SUCCESS, /*!< Transfer submitted successfully */ + MOCK_USB_TRANSFER_ERROR, /*!< Transfer error */ + MOCK_USB_TRANSFER_TIMEOUT /*!< Transfer timeout */ +} mock_usb_transfer_response_t; + + +/** + * @brief Host test fixture, for installing CDC-ACM host driver + * + * - This function calls the real cdc_acm_host_install() function with USB Host stack CMock expectations + * + * @param[in] driver_config configuration for CDC-ACM Host + * + * @note This function returns the same parameters as the real the cdc_acm_host_install() function + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The CDC driver is already installed or USB host library is not installed + * - ESP_ERR_NO_MEM: Not enough memory for installing the driver + */ +esp_err_t mock_cdc_acm_host_install(const cdc_acm_host_driver_config_t *driver_config); + +/** + * @brief Host test fixture, for uninstalling CDC-ACM host driver + * + * - This function calls the real cdc_acm_host_uninstall() function with USB Host stack CMock expectations + * + * @note This function returns the same parameters as the real the cdc_acm_host_uninstall() function + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The CDC driver is not installed or not all CDC devices are closed + * - ESP_ERR_NOT_FINISHED: The CDC driver failed to uninstall completely + */ +esp_err_t mock_cdc_acm_host_uninstall(void); + +/** + * @brief Host test fixture, for opening CDC-ACM device + * + * - This function calls the real cdc_acm_host_open() functions with USB Host stack CMock expectations + * + * @param[in] device_addr Device's Address + * @param[in] vid Device's Vendor ID + * @param[in] pid Device's Product ID + * @param[in] interface_idx Index of device's interface used for CDC-ACM communication + * @param[in] dev_config Configuration structure of the device + * @param[out] cdc_hdl_ret CDC device handle + * + * @note This function returns the same parameters as the real the cdc_acm_host_open() function + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The CDC driver is not installed + * - ESP_ERR_INVALID_ARG: dev_config or cdc_hdl_ret is NULL + * - ESP_ERR_NO_MEM: Not enough memory for opening the device + * - ESP_ERR_NOT_FOUND: USB device with specified VID/PID is not connected or does not have specified interface + */ +esp_err_t mock_cdc_acm_host_open(uint8_t device_addr, uint16_t vid, uint16_t pid, uint8_t interface_idx, const cdc_acm_host_device_config_t *dev_config, cdc_acm_dev_hdl_t *cdc_hdl_ret); + +/** + * @brief Host test fixture, for closing CDC-ACM device + * + * - This function calls the real cdc_acm_host_close() functions with USB Host stack CMock expectations + * + * @param[in] cdc_hdl CDC handle obtained from cdc_acm_host_open() + * @param[in] interface_idx Index of device's interface used for CDC-ACM communication + * + * @note This function returns the same parameters as the real the cdc_acm_host_open() function + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The CDC driver is not installed + * - ESP_ERR_INVALID_ARG: dev_config or cdc_hdl_ret is NULL + * - ESP_ERR_NO_MEM: Not enough memory for opening the device + * - ESP_ERR_NOT_FOUND: USB device with specified VID/PID is not connected or does not have specified interface + */ +esp_err_t mock_cdc_acm_host_close(cdc_acm_dev_hdl_t *cdc_hdl, uint8_t interface_idx); + +/** + * @brief Send transfer to mocked device + * + * - This function calls the real cdc_acm_host_data_tx_blocking() functions with USB Host stack CMock expectations + * + * @param[in] cdc_hdl CDC handle obtained from cdc_acm_host_open() + * @param[in] data Data to be sent + * @param[in] data_len Data length + * @param[in] timeout_ms Timeout in [ms] + * @param[in] transfer_response Intended transfer response (for testing multiple scenarios) + * + * @note This function returns the same parameters as the real the cdc_acm_host_data_tx_blocking() function + * @return + * - ESP_OK: Success + * - ESP_ERR_NOT_SUPPORTED: The device was opened as read only + * - ESP_ERR_INVALID_ARG: Invalid input arguments + * - ESP_ERR_INVALID_SIZE: Invalid size of data to be sent + * - ESP_ERR_TIMEOUT: tx transfer has timed out + * - ESP_ERR_INVALID_RESPONSE: Invalid transfer response + */ +esp_err_t mock_cdc_acm_host_data_tx_blocking(cdc_acm_dev_hdl_t cdc_hdl, const uint8_t *data, size_t data_len, uint32_t timeout_ms, mock_usb_transfer_response_t transfer_response); diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_device_interaction.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/main/test_device_interaction.cpp new file mode 100644 index 00000000..90387f4c --- /dev/null +++ b/host/class/cdc/usb_host_cdc_acm/host_test/main/test_device_interaction.cpp @@ -0,0 +1,188 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "cdc_descriptors.hpp" +#include "test_parsing_checker.hpp" +#include "usb/cdc_acm_host.h" +#include "mock_add_usb_device.h" +#include "common_test_fixtures.hpp" +#include "usb_helpers.h" +#include "cdc_host_descriptor_parsing.h" + +extern "C" { +#include "Mockusb_host.h" + +#include "Mockqueue.h" +#include "Mocktask.h" +#include "Mockidf_additions.h" +#include "Mockportmacro.h" +#include "Mockevent_groups.h" +} + +/** + * @brief Add mocked devices + * + * Mocked devices are defined by a device descriptor, a configuration descriptor and a device address + */ +static void _add_mocked_devices(void) +{ + // Init mocked devices list at the beginning of the test + usb_host_mock_dev_list_init(); + + // Fill mocked devices list + + // ASIX Electronics Corp. AX88772A Fast Ethernet (FS descriptor) + REQUIRE(ESP_OK == usb_host_mock_add_device(1, (const usb_device_desc_t *)premium_cord_device_desc_fs, + (const usb_config_desc_t *)premium_cord_config_desc_fs)); + + // ASIX Electronics Corp. AX88772B (FS descriptor) + REQUIRE(ESP_OK == usb_host_mock_add_device(2, (const usb_device_desc_t *)i_tec_device_desc_fs, + (const usb_config_desc_t *)i_tec_config_desc_fs)); + + // FTDI chip dual (FS descriptor) + REQUIRE(ESP_OK == usb_host_mock_add_device(3, (const usb_device_desc_t *)ftdi_device_desc_fs_hs, + (const usb_config_desc_t *)ftdi_config_desc_fs)); + + // TTL232RG (FS descriptor) + REQUIRE(ESP_OK == usb_host_mock_add_device(4, (const usb_device_desc_t *)ttl232_device_desc, + (const usb_config_desc_t *)ttl232_config_desc)); + + // CP210x (FS descriptor) + REQUIRE(ESP_OK == usb_host_mock_add_device(5, (const usb_device_desc_t *)cp210x_device_desc, + (const usb_config_desc_t *)cp210x_config_desc)); +} + +/** + * @brief Submit mock transfers to opened mocked device + * + * This function will submit couple of transfers to the mocked opened device, to test interaction of CDC-ACM host driver + * with the mocked USB Host stack and mocked USB device + * + * @param[in] dev CDC handle obtained from cdc_acm_host_open() + */ +static void _submit_mock_transfer(cdc_acm_dev_hdl_t *dev) +{ + const uint8_t tx_buf[] = "HELLO"; + // Submit transfer successfully + REQUIRE(ESP_OK == mock_cdc_acm_host_data_tx_blocking(*dev, tx_buf, sizeof(tx_buf), 1000, MOCK_USB_TRANSFER_SUCCESS)); + // Submit transfer which will fail to submit + REQUIRE(ESP_ERR_INVALID_RESPONSE == mock_cdc_acm_host_data_tx_blocking(*dev, tx_buf, sizeof(tx_buf), 1000, MOCK_USB_TRANSFER_ERROR)); + // Submit transfer which times out + REQUIRE(ESP_ERR_TIMEOUT == mock_cdc_acm_host_data_tx_blocking(*dev, tx_buf, sizeof(tx_buf), 1000, MOCK_USB_TRANSFER_TIMEOUT)); +} + + +SCENARIO("Interact with mocked USB devices") +{ + // We will put device adding to the SECTION, to run it just once, not repeatedly for all the following SECTIONs + SECTION("Add mocked devices") { + + _add_mocked_devices(); + + // Optionally, print all the devices + //usb_host_mock_print_mocked_devices(0); + } + + GIVEN("Mocked devices are added to the device list") { + // Install CDC-ACM driver + REQUIRE(ESP_OK == mock_cdc_acm_host_install(nullptr)); + + cdc_acm_dev_hdl_t dev = nullptr; + const cdc_acm_host_device_config_t dev_config = { + .connection_timeout_ms = 1000, + .out_buffer_size = 100, + .in_buffer_size = 100, + .event_cb = nullptr, + .data_cb = nullptr, + .user_arg = nullptr, + }; + + // We can use this approach, in case the device opening and closing are not our DUT functions + + // Eg, in case we want to open a device, test something with the opened device open and close the device + // Test fixtures for seamless device opening and closing mock_cdc_acm_host_open(), mock_cdc_acm_host_close() + SECTION("Interact with device: ASIX Electronics Corp. AX88772A Fast Ethernet") { + + // Define details of a device which will be opened + const uint16_t vid = 0xB95, pid = 0x772A; + const uint8_t device_address = 1, interface_index = 0; + + // Open a device + REQUIRE(ESP_OK == mock_cdc_acm_host_open(device_address, vid, pid, interface_index, &dev_config, &dev)); + REQUIRE(dev != nullptr); + // Interact with the device - submit mocked transfers + _submit_mock_transfer(&dev); + // Close the device + REQUIRE(ESP_OK == mock_cdc_acm_host_close(&dev, interface_index)); + } + + SECTION("Interact with device: ASIX Electronics Corp. AX88772B") { + + // Define details of a device which will be opened + const uint16_t vid = 0xB95, pid = 0x772B; + const uint8_t device_address = 2, interface_index = 0; + + // Open a device + REQUIRE(ESP_OK == mock_cdc_acm_host_open(device_address, vid, pid, interface_index, &dev_config, &dev)); + REQUIRE(dev != nullptr); + // Interact with the device - submit mocked transfers + _submit_mock_transfer(&dev); + // Close the device + REQUIRE(ESP_OK == mock_cdc_acm_host_close(&dev, interface_index)); + } + + SECTION("Interact with device: FTDI chip dual (FS descriptor)") { + + // Define details of a device which will be opened + const uint16_t vid = 0x403, pid = 0x6010; + const uint8_t device_address = 3, interface_index = 0; + + // Open a device + REQUIRE(ESP_OK == mock_cdc_acm_host_open(device_address, vid, pid, interface_index, &dev_config, &dev)); + REQUIRE(dev != nullptr); + // Interact with the device - submit mocked transfers + _submit_mock_transfer(&dev); + // Close the device + REQUIRE(ESP_OK == mock_cdc_acm_host_close(&dev, interface_index)); + } + + SECTION("Interact with device: TTL232RG (FS descriptor)") { + + // Define details of a device which will be opened + const uint16_t vid = 0x403, pid = 0x6001; + const uint8_t device_address = 4, interface_index = 0; + + // Open a device + REQUIRE(ESP_OK == mock_cdc_acm_host_open(device_address, vid, pid, interface_index, &dev_config, &dev)); + REQUIRE(dev != nullptr); + // Interact with the device - submit mocked transfers + _submit_mock_transfer(&dev); + // Close the device + REQUIRE(ESP_OK == mock_cdc_acm_host_close(&dev, interface_index)); + } + + SECTION("Interact with device: CP210x") { + + // Define details of a device which will be opened + const uint16_t vid = 0x10C4, pid = 0xEA60; + const uint8_t device_address = 5, interface_index = 0; + + // Open a device + REQUIRE(ESP_OK == mock_cdc_acm_host_open(device_address, vid, pid, interface_index, &dev_config, &dev)); + REQUIRE(dev != nullptr); + // Interact with the device - submit mocked transfers + _submit_mock_transfer(&dev); + // Close the device + REQUIRE(ESP_OK == mock_cdc_acm_host_close(&dev, interface_index)); + } + + // Uninstall CDC-ACM driver + REQUIRE(ESP_OK == mock_cdc_acm_host_uninstall()); + } +} diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_opening_device.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/main/test_opening_device.cpp new file mode 100644 index 00000000..c1e4cf68 --- /dev/null +++ b/host/class/cdc/usb_host_cdc_acm/host_test/main/test_opening_device.cpp @@ -0,0 +1,255 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "cdc_descriptors.hpp" +#include "test_parsing_checker.hpp" +#include "usb/cdc_acm_host.h" +#include "mock_add_usb_device.h" +#include "common_test_fixtures.hpp" +#include "usb_helpers.h" +#include "cdc_host_descriptor_parsing.h" + +extern "C" { +#include "Mockusb_host.h" + +#include "Mockqueue.h" +#include "Mocktask.h" +#include "Mockidf_additions.h" +#include "Mockportmacro.h" +#include "Mockevent_groups.h" +} + +/** + * @brief Add mocked devices + * + * Mocked devices are defined by a device descriptor, a configuration descriptor and a device address + */ +static void _add_mocked_devices(void) +{ + // Init mocked devices list at the beginning of the test + usb_host_mock_dev_list_init(); + + // Fill mocked devices list + // CP210x (FS descriptor) + REQUIRE(ESP_OK == usb_host_mock_add_device(5, (const usb_device_desc_t *)cp210x_device_desc, + (const usb_config_desc_t *)cp210x_config_desc)); +} + +/** + * @brief Open mocked device from mocked device list + * + * @note Device(s) must be firstly added to mocked device list by usb_host_mock_add_device() + * + * @param[in] vid VID of a device to be opened + * @param[in] pid PID of a device to be opened + * @param[in] interface_numer Interface number of a device to be opened + * @param[in] dev_config CDC-ACM device configuration + * @param[out] dev device handle + */ +static void _open_device(uint16_t vid, uint16_t pid, uint8_t interface_number, const cdc_acm_host_device_config_t *dev_config, cdc_acm_dev_hdl_t *dev) +{ + xQueueSemaphoreTake_ExpectAnyArgsAndReturn(pdTRUE); + vTaskSetTimeOutState_ExpectAnyArgs(); + + // Device opening + usb_host_device_addr_list_fill_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_device_addr_list_fill_AddCallback(usb_host_device_addr_list_fill_callback); + + // We are expecting usb_host_device_open, usb_host_get_device_descriptor usb_host_device_close + // to be called at least mocked_devs_count times + // Get number of mocked USB devices in mocked device list + const int mocked_devs_count = usb_host_mock_get_devs_count(); + for (int i = 0; i < mocked_devs_count; i++) { + usb_host_device_open_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_device_close_ExpectAnyArgsAndReturn(ESP_OK); + } + usb_host_device_open_AddCallback(usb_host_device_open_callback); + usb_host_get_device_descriptor_AddCallback(usb_host_get_device_descriptor_callback); + usb_host_device_close_AddCallback(usb_host_device_close_callback); + + // We have found the device by specified PID VID + + // Get Device and Configuration descriptors of the correct device + usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_active_config_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_active_config_descriptor_AddCallback(usb_host_get_active_config_descriptor_callback); + + // Call cdc_acm_transfer_allocate + int ctrl_transfer_semaphore, data_out_transfer_semaphore; + int ctrl_transfer_mutex, data_out_transfer_mutex; + + // Setup control transfer + usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); + // Semaphore: cdc_dev->ctrl_transfer->context = xSemaphoreCreateBinary(); + xQueueGenericCreate_ExpectAnyArgsAndReturn(reinterpret_cast(&ctrl_transfer_semaphore)); + // Mutex: cdc_dev->ctrl_mux = xSemaphoreCreateMutex(); + xQueueCreateMutex_ExpectAnyArgsAndReturn(reinterpret_cast(&ctrl_transfer_mutex)); + + // Setup IN data transfer + if (dev_config->in_buffer_size) { + usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); + } + + // Setup OUT bulk transfer + if (dev_config->out_buffer_size) { + usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); + // Semaphore: cdc_dev->data.out_xfer->context = xSemaphoreCreateBinary(); + xQueueGenericCreate_ExpectAnyArgsAndReturn(reinterpret_cast(&data_out_transfer_semaphore)); + // Mutex: cdc_dev->data.out_mux = xSemaphoreCreateMutex(); + xQueueCreateMutex_ExpectAnyArgsAndReturn(reinterpret_cast(&data_out_transfer_mutex)); + } + + // Register callback + usb_host_transfer_alloc_AddCallback(usb_host_transfer_alloc_callback); + + // Call cdc_acm_start + // Make sure that the interface_number has been claimed + usb_host_interface_claim_ExpectAndReturn(nullptr, nullptr, interface_number, 0, ESP_OK); + usb_host_interface_claim_IgnoreArg_client_hdl(); + usb_host_interface_claim_IgnoreArg_dev_hdl(); + usb_host_interface_claim_IgnoreArg_bAlternateSetting(); + + usb_host_transfer_submit_ExpectAnyArgsAndReturn(ESP_OK); + xQueueGenericSend_ExpectAnyArgsAndReturn(pdTRUE); + + // Call the real DUT function cdc_acm_host_open() + // Expect ESP_OK and dev_hdl non nullptr + REQUIRE(ESP_OK == cdc_acm_host_open(vid, pid, interface_number, dev_config, dev)); + REQUIRE(dev != nullptr); +} + +/** + * @brief Just print the device and configuration descriptor of opened mocked device + * + * @note Device must be firstly opened by cdc_acm_host_open() + * + * @param[in] dev device handle + */ +static void _print_descriptor(cdc_acm_dev_hdl_t *dev) +{ + // Test that the mocked device was opened and can be used by the CDC-ACM host driver + usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_active_config_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + + // Call DUT function cdc_acm_host_desc_print + // Expect device and configuration descriptors will be printed + cdc_acm_host_desc_print(*dev); +} + +/** + * @brief Close mocked device + * + * @note Device must be firstly opened by cdc_acm_host_open() + * + * @param[in] interface_numer Interface number of a device to be closed + * @param[in] dev_config CDC-ACM device configuration + * @param[out] dev device handle + */ +static void _close_device(uint8_t device_address, uint8_t interface_idx, const cdc_acm_host_device_config_t *dev_config, cdc_acm_dev_hdl_t *dev) +{ + // Get IN_EP address + const usb_config_desc_t *config_desc; + const usb_device_desc_t *device_desc; + cdc_parsed_info_t cdc_info; + usb_host_mock_get_config_descriptor_by_address(device_address, &config_desc); + usb_host_mock_get_device_descriptor_by_address(device_address, &device_desc); + cdc_parse_interface_descriptor(device_desc, config_desc, interface_idx, &cdc_info); + + xQueueSemaphoreTake_ExpectAnyArgsAndReturn(pdTRUE); + + // Cancel pooling of Interrupt IN endpoint -> halt, flush, clear + // Make sure to halt, flush, clear correct endpoints + usb_host_endpoint_halt_ExpectAndReturn(nullptr, cdc_info.in_ep->bEndpointAddress, ESP_OK); + usb_host_endpoint_halt_IgnoreArg_dev_hdl(); + + usb_host_endpoint_flush_ExpectAndReturn(nullptr, cdc_info.in_ep->bEndpointAddress, ESP_OK); + usb_host_endpoint_flush_IgnoreArg_dev_hdl(); + + usb_host_endpoint_clear_ExpectAndReturn(nullptr, cdc_info.in_ep->bEndpointAddress, ESP_OK); + usb_host_endpoint_clear_IgnoreArg_dev_hdl(); + + // Release data interface, make sure to release a correct interface + usb_host_interface_release_ExpectAndReturn(nullptr, nullptr, interface_idx, ESP_OK); + usb_host_interface_release_IgnoreArg_client_hdl(); + usb_host_interface_release_IgnoreArg_dev_hdl(); + + // Call cdc_acm_device_remove + // Free ctrl transfer + usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); + vQueueDelete_ExpectAnyArgs(); + vQueueDelete_ExpectAnyArgs(); + + // Free in transfer + if (dev_config->in_buffer_size) { + usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); + } + + // Free out transfer + if (dev_config->out_buffer_size) { + usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); + vQueueDelete_ExpectAnyArgs(); + vQueueDelete_ExpectAnyArgs(); + } + usb_host_transfer_free_AddCallback(usb_host_transfer_free_callback); + + usb_host_device_close_ExpectAnyArgsAndReturn(ESP_OK); + xQueueGenericSend_ExpectAnyArgsAndReturn(pdTRUE); + + // Call the real DUT function cdc_acm_host_close() + // Expect ESP_OK + REQUIRE(ESP_OK == cdc_acm_host_close(*dev)); +} + +SCENARIO("Test mocked device opening and closing") +{ + // We will put device adding to the SECTION, to run it just once, not repeatedly for all the following SECTIONs + // (if multiple sections are present) + SECTION("Add mocked device") { + _add_mocked_devices(); + + // Optionally, print all the devices + //usb_host_mock_print_mocked_devices(0); + } + + GIVEN("Mocked device is added to the device list") { + // Install CDC-ACM driver + REQUIRE(ESP_OK == mock_cdc_acm_host_install(nullptr)); + + cdc_acm_dev_hdl_t dev = nullptr; + const cdc_acm_host_device_config_t dev_config = { + .connection_timeout_ms = 1000, + .out_buffer_size = 100, + .in_buffer_size = 100, + .event_cb = nullptr, + .data_cb = nullptr, + .user_arg = nullptr, + }; + + // We can use this approach, in case the device opening and closing are our DUT functions + // Eg, in case we want to test device opening and closing itself + SECTION("Test device opening and closing") { + + // Define input parameters for cdc_acm_host_open + const uint16_t vid = 0x10C4, pid = 0xEA60; + const uint8_t device_address = 5; + const uint8_t interface_number = 0; + + // ------------------------------------------ Open a device ------------------------------------------------ + _open_device(vid, pid, interface_number, &dev_config, &dev); + // ------------------------------------------ Get device info (use the device) ----------------------------- + _print_descriptor(&dev); + // ------------------------------------------ Close the device --------------------------------------------- + _close_device(device_address, interface_number, &dev_config, &dev); + } + + // Uninstall CDC-ACM driver + REQUIRE(ESP_OK == mock_cdc_acm_host_uninstall()); + } +} diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_unit_public_api.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/main/test_unit_public_api.cpp index d4424848..93084e81 100644 --- a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_unit_public_api.cpp +++ b/host/class/cdc/usb_host_cdc_acm/host_test/main/test_unit_public_api.cpp @@ -9,6 +9,7 @@ #include #include "usb/cdc_acm_host.h" +#include "esp_system.h" extern "C" { #include "Mockusb_host.h" @@ -19,16 +20,33 @@ extern "C" { #include "Mockevent_groups.h" } -SCENARIO("CDC-ACM Host install") +int task_handle_ptr; +// Ensure task_handle is non nullptr, as it is used in ReturnThruPtr type of Cmock function +TaskHandle_t task_handle = reinterpret_cast(&task_handle_ptr); +int sem; +int event_group; + + +SCENARIO("CDC-ACM Host install/uninstall") { // CDC-ACM Host driver config set to nullptr GIVEN("NO CDC-ACM Host driver config, driver not installed") { - TaskHandle_t task_handle; - int sem; - int event_group; - // Call cdc_acm_host_install with cdc_acm_host_driver_config set to nullptr, fail to create EventGroup + // Try to uninstall CDC ACM Host (not previously installed) + // Expect fail because of p_cdc_acm_obj being nullptr + SECTION("Try to uninstall not installed CDC ACM Host") { + + vPortEnterCritical_Expect(); + vPortExitCritical_Expect(); + + // Call the DUT function, expect ESP_ERR_INVALID_STATE + REQUIRE(ESP_ERR_INVALID_STATE == cdc_acm_host_uninstall()); + } + + // Try to install CDC ACM Host, induce an error during install + // Expect fail to create EventGroup SECTION("Fail to create EventGroup") { + // Create an EventGroup, return nullptr, so the EventGroup is not created successfully xEventGroupCreate_ExpectAndReturn(nullptr); // We should be calling xSemaphoreCreteMutex_ExpectAnyArgsAndRetrun instead of xQueueCreateMutex_ExpectAnyArgsAndReturn @@ -48,8 +66,10 @@ SCENARIO("CDC-ACM Host install") REQUIRE(ESP_ERR_NO_MEM == cdc_acm_host_install(nullptr)); } - // Call cdc_acm_host_install, expect to successfully install the CDC ACM host + // Install CDC ACM Host + // Expect to successfully install the CDC ACM host SECTION("Successfully install CDC ACM Host") { + // Create an EventGroup, return event group handle, so the EventGroup is created successfully xEventGroupCreate_ExpectAndReturn(reinterpret_cast(&event_group)); // We should be calling xSemaphoreCreteMutex_ExpectAnyArgsAndRetrun instead of xQueueCreateMutex_ExpectAnyArgsAndReturn @@ -74,4 +94,42 @@ SCENARIO("CDC-ACM Host install") REQUIRE(ESP_OK == cdc_acm_host_install(nullptr)); } } + + GIVEN("NO CDC-ACM Host driver config, driver already installed") { + + // Try to install CDC ACM Host again, while it is already installed (from the previous test section) + // Expect fail because of p_cdc_acm_obj being non nullptr + SECTION("Try to install CDC ACM Host again") { + + // Call the DUT function, expect ESP_ERR_INVALID_STATE + REQUIRE(ESP_ERR_INVALID_STATE == cdc_acm_host_install(nullptr)); + } + + // Uninstall CDC ACM Host + // Expect to successfully uninstall the CDC ACM Host + SECTION("Successfully uninstall CDC ACM Host") { + + vPortEnterCritical_Expect(); + vPortExitCritical_Expect(); + xQueueSemaphoreTake_ExpectAndReturn(reinterpret_cast(&sem), portMAX_DELAY, pdTRUE); + vPortEnterCritical_Expect(); + vPortExitCritical_Expect(); + + // Signal to CDC task to stop, unblock it and wait for its deletion + xEventGroupSetBits_ExpectAndReturn(reinterpret_cast(&event_group), BIT0, pdTRUE); + + // Call mocked function from USB Host + // return ESP_OK, so the client si unblocked successfully + usb_host_client_unblock_ExpectAnyArgsAndReturn(ESP_OK); + xEventGroupWaitBits_ExpectAndReturn(reinterpret_cast(&event_group), BIT1, pdFALSE, pdFALSE, pdMS_TO_TICKS(100), pdTRUE); + + // Free remaining resources + vEventGroupDelete_Expect(reinterpret_cast(&event_group)); + xQueueGenericSend_ExpectAnyArgsAndReturn(pdTRUE); + vQueueDelete_Expect(reinterpret_cast(&sem)); + + // Call the DUT function, expect ESP_OK + REQUIRE(ESP_OK == cdc_acm_host_uninstall()); + } + } } From 64aa8b470e8dade36f426347525401a7fcf64428 Mon Sep 17 00:00:00 2001 From: "peter.marcisovsky" Date: Thu, 28 Nov 2024 16:17:14 +0100 Subject: [PATCH 2/3] feat(cdc_acm): Freertos used as real component in device interaction tests --- .../{main => descriptors}/cdc_descriptors.hpp | 0 .../device_interaction/CMakeLists.txt | 12 + .../host_test/device_interaction/README.md | 31 ++ .../device_interaction/main/CMakeLists.txt | 9 + .../main/common_test_fixtures.cpp | 314 ++++++++++++++ .../main/common_test_fixtures.hpp | 37 -- .../main/idf_component.yml | 2 +- .../main/test_device_interaction.cpp | 34 +- .../device_interaction/main/test_main.cpp | 28 ++ .../main/test_opening_device.cpp | 123 ++++++ .../sdkconfig.defaults | 0 .../host_test/main/common_test_fixtures.cpp | 401 ------------------ .../host_test/main/test_opening_device.cpp | 255 ----------- .../{ => parsing_tests}/CMakeLists.txt | 0 .../host_test/{ => parsing_tests}/README.md | 1 + .../{ => parsing_tests}/main/CMakeLists.txt | 4 +- .../parsing_tests/main/idf_component.yml | 5 + .../main/test_parsing_checker.hpp | 0 .../main/test_parsing_ethernet_converters.cpp | 0 .../main/test_parsing_modems.cpp | 0 .../main/test_parsing_tinyusb_devices.cpp | 0 .../main/test_parsing_uart_converters.cpp | 0 .../main/test_unit_public_api.cpp | 0 .../parsing_tests/sdkconfig.defaults | 8 + 24 files changed, 553 insertions(+), 711 deletions(-) rename host/class/cdc/usb_host_cdc_acm/host_test/{main => descriptors}/cdc_descriptors.hpp (100%) create mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/CMakeLists.txt create mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/README.md create mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/CMakeLists.txt create mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/common_test_fixtures.cpp rename host/class/cdc/usb_host_cdc_acm/host_test/{ => device_interaction}/main/common_test_fixtures.hpp (80%) rename host/class/cdc/usb_host_cdc_acm/host_test/{ => device_interaction}/main/idf_component.yml (72%) rename host/class/cdc/usb_host_cdc_acm/host_test/{ => device_interaction}/main/test_device_interaction.cpp (89%) create mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/test_main.cpp create mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/test_opening_device.cpp rename host/class/cdc/usb_host_cdc_acm/host_test/{ => device_interaction}/sdkconfig.defaults (100%) delete mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.cpp delete mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/main/test_opening_device.cpp rename host/class/cdc/usb_host_cdc_acm/host_test/{ => parsing_tests}/CMakeLists.txt (100%) rename host/class/cdc/usb_host_cdc_acm/host_test/{ => parsing_tests}/README.md (93%) rename host/class/cdc/usb_host_cdc_acm/host_test/{ => parsing_tests}/main/CMakeLists.txt (72%) create mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/idf_component.yml rename host/class/cdc/usb_host_cdc_acm/host_test/{ => parsing_tests}/main/test_parsing_checker.hpp (100%) rename host/class/cdc/usb_host_cdc_acm/host_test/{ => parsing_tests}/main/test_parsing_ethernet_converters.cpp (100%) rename host/class/cdc/usb_host_cdc_acm/host_test/{ => parsing_tests}/main/test_parsing_modems.cpp (100%) rename host/class/cdc/usb_host_cdc_acm/host_test/{ => parsing_tests}/main/test_parsing_tinyusb_devices.cpp (100%) rename host/class/cdc/usb_host_cdc_acm/host_test/{ => parsing_tests}/main/test_parsing_uart_converters.cpp (100%) rename host/class/cdc/usb_host_cdc_acm/host_test/{ => parsing_tests}/main/test_unit_public_api.cpp (100%) create mode 100644 host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/sdkconfig.defaults diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/cdc_descriptors.hpp b/host/class/cdc/usb_host_cdc_acm/host_test/descriptors/cdc_descriptors.hpp similarity index 100% rename from host/class/cdc/usb_host_cdc_acm/host_test/main/cdc_descriptors.hpp rename to host/class/cdc/usb_host_cdc_acm/host_test/descriptors/cdc_descriptors.hpp diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/CMakeLists.txt b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/CMakeLists.txt new file mode 100644 index 00000000..b97e0a27 --- /dev/null +++ b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) + +list(APPEND EXTRA_COMPONENT_DIRS + "$ENV{IDF_PATH}/tools/mocks/usb/" + #"$ENV{IDF_PATH}/tools/mocks/freertos/" We are using freertos as real component + ) + +add_definitions("-DCMOCK_MEM_DYNAMIC") +project(host_test_usb_cdc) diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/README.md b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/README.md new file mode 100644 index 00000000..1e0ecc65 --- /dev/null +++ b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/README.md @@ -0,0 +1,31 @@ +| Supported Targets | Linux | +| ----------------- | ----- | + +# Description + +This directory contains test code for `USB Host CDC-ACM` driver. Namely: +* Interactions with Mocked device added to the CDC-ACM driver (Device open, send mocked transfers, device close) + +Tests are written using [Catch2](https://github.com/catchorg/Catch2) test framework, use CMock, so you must install Ruby on your machine to run them. + +This test directory uses freertos as real component +# Build + +Tests build regularly like an idf project. Currently only working on Linux machines. + +``` +idf.py --preview set-target linux +idf.py build +``` + +# Run + +The build produces an executable in the build folder. + +Just run: + +``` +./build/host_test_usb_cdc.elf +``` + +The test executable have some options provided by the test framework. diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/CMakeLists.txt b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/CMakeLists.txt new file mode 100644 index 00000000..34d3f323 --- /dev/null +++ b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/CMakeLists.txt @@ -0,0 +1,9 @@ +idf_component_register(SRC_DIRS . + REQUIRES cmock usb + INCLUDE_DIRS "../../descriptors" . + PRIV_INCLUDE_DIRS "../../../private_include" + WHOLE_ARCHIVE) + +# Currently 'main' for IDF_TARGET=linux is defined in freertos component. +# Since we are using a freertos mock here, need to let Catch2 provide 'main'. +#target_link_libraries(${COMPONENT_LIB} PRIVATE Catch2WithMain) diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/common_test_fixtures.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/common_test_fixtures.cpp new file mode 100644 index 00000000..7cc88f7e --- /dev/null +++ b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/common_test_fixtures.cpp @@ -0,0 +1,314 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "usb/cdc_acm_host.h" +#include "mock_add_usb_device.h" +#include "common_test_fixtures.hpp" +#include "cdc_host_descriptor_parsing.h" + +extern "C" { +#include "Mockusb_host.h" +} + +/** + * @brief CMock expectations for current CDC device + * + * Only used for mocked usb host expectations + * + * For example, based on the descriptors, we record that a certain device has CTRL EP, IN EP, OUT EP and NO notif EP + * Then, during the device opening we expect usb_host_transfer_alloc() exactly 3 times (CTRL, IN, OUT) + * Also, during the device closing we expect usb_host_transfer_free() exactly 3 times (CTRL, IN, OUT) + * Different device could have CTRL, IN, OUT and NOTIF, thus we must expect those mocked functions exactly 4 times + */ +typedef struct { + struct { + usb_transfer_t *out_xfer; + usb_transfer_t *in_xfer; + uint8_t in_bEndpointAddress; + uint8_t out_bEndpointAddress; + } data; + struct { + usb_transfer_t *xfer; + uint8_t bEndpointAddress; + } notif; +} cdc_dev_expects_t; + +static cdc_dev_expects_t *p_cdc_dev_expects = nullptr; + +/** + * @brief Create CMock expectations for current device + * + * This function creates CMock expectations for a USB device, + * + * @param[in] dev_address Device address + * @param[in] interface_idx Interface index to be used + * @param[in] dev_config CDC-ACM Host device config struct + * + * @return + * - ESP_OK: Mock expectations created successfully + * - ESP_ERR_NO_MEM: Not enough memory + */ +static esp_err_t _create_cmock_expectations(uint8_t dev_address, uint8_t interface_idx, const cdc_acm_host_device_config_t *dev_config) +{ + cdc_dev_expects_t *cdc_dev_expects = (cdc_dev_expects_t *)calloc(1, sizeof(cdc_dev_expects_t)); + if (cdc_dev_expects == nullptr) { + return ESP_ERR_NO_MEM; + } + + int notif_xfer, data_in_xfer, data_out_xfer; + const usb_config_desc_t *config_desc; + const usb_device_desc_t *device_desc; + cdc_parsed_info_t cdc_info; + usb_host_mock_get_config_descriptor_by_address(dev_address, &config_desc); + usb_host_mock_get_device_descriptor_by_address(dev_address, &device_desc); + cdc_parse_interface_descriptor(device_desc, config_desc, interface_idx, &cdc_info); + + // Get IN and OUT endpoints addresses + cdc_dev_expects->data.in_bEndpointAddress = cdc_info.in_ep->bEndpointAddress; + cdc_dev_expects->data.out_bEndpointAddress = cdc_info.out_ep->bEndpointAddress; + + // Get notification endpoint address and check if notification transfer is allocated (if notif. EP exists) + if (cdc_info.notif_ep) { + cdc_dev_expects->notif.bEndpointAddress = cdc_info.notif_ep->bEndpointAddress; + cdc_dev_expects->notif.xfer = reinterpret_cast(¬if_xfer); + } else { + cdc_dev_expects->notif.bEndpointAddress = 0; + cdc_dev_expects->notif.xfer = nullptr; + } + + // Check, if IN data transfer is allocated + if (dev_config->in_buffer_size) { + cdc_dev_expects->data.in_xfer = reinterpret_cast(&data_in_xfer); + } else { + cdc_dev_expects->data.in_xfer = nullptr; + } + + // Check if OUT data transfer is allocated + if (dev_config->out_buffer_size) { + cdc_dev_expects->data.out_xfer = reinterpret_cast(&data_out_xfer); + } else { + cdc_dev_expects->data.out_xfer = nullptr; + } + + p_cdc_dev_expects = cdc_dev_expects; + return ESP_OK; +} + +/** + * @brief free space allocated for p_cdc_dev_expects + */ +static void _delete_cmock_expectations(void) +{ + free(p_cdc_dev_expects); + p_cdc_dev_expects = nullptr; +} + +/** + * @brief Reset endpoint halt -> flush -> clear + * + * @param ep_address[in] Endpoint address to be reset + */ +static void _mock_cdc_acm_reset_transfer_endpoint(uint8_t ep_address) +{ + // Expect correct ep_address for all (halt, flush, clear) + usb_host_endpoint_halt_ExpectAndReturn(nullptr, ep_address, ESP_OK); + usb_host_endpoint_halt_IgnoreArg_dev_hdl(); + + usb_host_endpoint_flush_ExpectAndReturn(nullptr, ep_address, ESP_OK); + usb_host_endpoint_flush_IgnoreArg_dev_hdl(); + + usb_host_endpoint_clear_ExpectAndReturn(nullptr, ep_address, ESP_OK); + usb_host_endpoint_clear_IgnoreArg_dev_hdl(); +} + +esp_err_t mock_cdc_acm_host_install(const cdc_acm_host_driver_config_t *driver_config) +{ + usb_host_client_register_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_client_register_AddCallback(usb_host_client_register_mock_callback); + + usb_host_client_handle_events_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_client_handle_events_AddCallback(usb_host_client_handle_events_mock_callback); + + // Call the real function cdc_acm_host_install() + return cdc_acm_host_install(driver_config); +} + +esp_err_t mock_cdc_acm_host_uninstall(void) +{ + // Call mocked function from USB Host + // return ESP_OK, so the client si unblocked successfully + usb_host_client_unblock_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_client_unblock_AddCallback(usb_host_client_unblock_mock_callback); + + + usb_host_client_deregister_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_client_deregister_AddCallback(usb_host_client_deregister_mock_callback); + + _delete_cmock_expectations(); + + // Call the real function, cdc_acm_host_uninstall() + return cdc_acm_host_uninstall(); +} + +esp_err_t mock_cdc_acm_host_open(uint8_t dev_address, uint16_t vid, uint16_t pid, uint8_t interface_idx, const cdc_acm_host_device_config_t *dev_config, cdc_acm_dev_hdl_t *cdc_hdl_ret) +{ + esp_err_t ret = _create_cmock_expectations(dev_address, interface_idx, dev_config); + if (ret != ESP_OK) { + return ret; // ESP_ERR_NO_MEM + } + + // Device opening + usb_host_device_addr_list_fill_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_device_addr_list_fill_AddCallback(usb_host_device_addr_list_fill_mock_callback); + + // We are expecting usb_host_device_open, usb_host_get_device_descriptor usb_host_device_close + // to be called at least mocked_devs_count times + const int mocked_devs_count = usb_host_mock_get_devs_count(); // Get number of mocked USB devices in mocked device list + for (int i = 0; i < mocked_devs_count; i++) { + usb_host_device_open_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_device_close_ExpectAnyArgsAndReturn(ESP_OK); + } + + usb_host_device_open_AddCallback(usb_host_device_open_mock_callback); + usb_host_get_device_descriptor_AddCallback(usb_host_get_device_descriptor_mock_callback); + usb_host_device_close_AddCallback(usb_host_device_close_mock_callback); + + // We have found the device by specified PID VID + + // Get Device and Configuration descriptors of the correct device + usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_active_config_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_active_config_descriptor_AddCallback(usb_host_get_active_config_descriptor_mock_callback); + + // Setup control transfer + usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); + + // Setup Notif transfer + if (p_cdc_dev_expects->notif.xfer) { + usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); + } + + // Setup IN data transfer + if (dev_config->in_buffer_size) { + usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); + } + + // Setup OUT bulk transfer + if (dev_config->out_buffer_size) { + usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); + } + + // Register callback + usb_host_transfer_alloc_AddCallback(usb_host_transfer_alloc_mock_callback); + + // Call cdc_acm_start + + // Claim data interface + // Make sure that the interface_idx has been claimed + usb_host_interface_claim_ExpectAndReturn(nullptr, nullptr, interface_idx, 0, ESP_OK); + usb_host_interface_claim_IgnoreArg_client_hdl(); // Ignore all function parameters, except interface_number + usb_host_interface_claim_IgnoreArg_dev_hdl(); + usb_host_interface_claim_IgnoreArg_bAlternateSetting(); + usb_host_transfer_submit_ExpectAnyArgsAndReturn(ESP_OK); + + // Claim notification interface (if supported) + if (p_cdc_dev_expects->notif.xfer) { + usb_host_interface_claim_ExpectAndReturn(nullptr, nullptr, interface_idx, 0, ESP_OK); + usb_host_interface_claim_IgnoreArg_client_hdl(); // Ignore all function parameters, except interface_number + usb_host_interface_claim_IgnoreArg_dev_hdl(); + usb_host_interface_claim_IgnoreArg_bAlternateSetting(); + usb_host_transfer_submit_ExpectAnyArgsAndReturn(ESP_OK); + } + + // Call the real function cdc_acm_host_open + // Expect ESP_OK and dev_hdl non nullptr + ret = cdc_acm_host_open(vid, pid, interface_idx, dev_config, cdc_hdl_ret); + + // If the cdc_acm_host_open() fails, delete the created cdc_device + if (ret != ESP_OK) { + _delete_cmock_expectations(); + } + return ret; +} + +esp_err_t mock_cdc_acm_host_close(cdc_acm_dev_hdl_t *cdc_hdl, uint8_t interface_number) +{ + // Cancel pooling of IN endpoint -> halt, flush, clear + _mock_cdc_acm_reset_transfer_endpoint(p_cdc_dev_expects->data.in_bEndpointAddress); + + // Cancel pooling of Notification endpoint -> halt, flush, clear + if (p_cdc_dev_expects->notif.xfer) { + _mock_cdc_acm_reset_transfer_endpoint(p_cdc_dev_expects->notif.bEndpointAddress); + } + + // Release data interface + usb_host_interface_release_ExpectAndReturn(nullptr, nullptr, interface_number, ESP_OK); + usb_host_interface_release_IgnoreArg_client_hdl(); // Ignore all function parameters, except interface_number + usb_host_interface_release_IgnoreArg_dev_hdl(); + + + // Free notif transfer + if (p_cdc_dev_expects->notif.xfer) { + usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); + p_cdc_dev_expects->notif.xfer = nullptr; + } + + // Free in transfer + if (p_cdc_dev_expects->data.in_xfer) { + usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); + p_cdc_dev_expects->data.in_xfer = nullptr; + } + + // Free out transfer + if (p_cdc_dev_expects->data.out_xfer) { + usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); + p_cdc_dev_expects->data.out_xfer = nullptr; + } + + // Call cdc_acm_device_remove + // Free ctrl transfer + usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_transfer_free_AddCallback(usb_host_transfer_free_mock_callback); + + usb_host_device_close_ExpectAnyArgsAndReturn(ESP_OK); + + // Call the real function cdc_acm_host_close + return cdc_acm_host_close(*cdc_hdl); +} + +esp_err_t mock_cdc_acm_host_data_tx_blocking(cdc_acm_dev_hdl_t cdc_hdl, const uint8_t *data, size_t data_len, uint32_t timeout_ms, mock_usb_transfer_response_t transfer_response) +{ + usb_host_transfer_submit_ExpectAnyArgsAndReturn(ESP_OK); + + switch (transfer_response) { + case MOCK_USB_TRANSFER_SUCCESS: { + // Make the submitted transfer to pass + usb_host_transfer_submit_AddCallback(usb_host_transfer_submit_success_mock_callback); + break; + } + case MOCK_USB_TRANSFER_ERROR: { + // Make the submitted transfer to fail + usb_host_transfer_submit_AddCallback(usb_host_transfer_submit_invalid_response_mock_callback); + break; + } + case MOCK_USB_TRANSFER_TIMEOUT: { + // Make the submitted transfer to be timed out + usb_host_transfer_submit_AddCallback(usb_host_transfer_submit_timeout_mock_callback); + // Reset out endpoint + _mock_cdc_acm_reset_transfer_endpoint(p_cdc_dev_expects->data.out_bEndpointAddress); + break; + } + default: + break; + } + + // Call the real function cdc_acm_host_data_tx_blocking() + return cdc_acm_host_data_tx_blocking(cdc_hdl, data, data_len, timeout_ms); +} diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.hpp b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/common_test_fixtures.hpp similarity index 80% rename from host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.hpp rename to host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/common_test_fixtures.hpp index efef54ac..bf3f1764 100644 --- a/host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.hpp +++ b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/common_test_fixtures.hpp @@ -5,46 +5,9 @@ */ #include "esp_err.h" -#include "freertos/queue.h" #pragma once -/** - * @brief CDC-ACM mocked driver object - * - * Variation of cdc_acm_obj_t *p_cdc_acm_obj; but for host tests - */ -typedef struct { - int open_close_mutex; - int cdc_acm_client_hdl; - int event_group; -} mock_cdc_acm_obj_t; - -/** - * @brief CDC-ACM device - * - * Variation of cdc_dev_t but for host tests - */ -typedef struct { - struct { - usb_transfer_t *out_xfer; - usb_transfer_t *in_xfer; - const usb_intf_desc_t *intf_desc; - QueueHandle_t out_mux; // This should be SemaphoreHandle_t, but freertos mock is not correct - QueueHandle_t out_sem; // cdc_dev->data.out_xfer->context = xSemaphoreCreateBinary(); - uint8_t in_bEndpointAddress; - uint8_t out_bEndpointAddress; - } data; - struct { - usb_transfer_t *xfer; - const usb_intf_desc_t *intf_desc; - uint8_t bEndpointAddress; - } notif; - usb_transfer_t *ctr_transfer; - QueueHandle_t ctrl_mux; // This should be SemaphoreHandle_t, but freertos mock is not correct - QueueHandle_t ctrl_sem; // cdc_dev->ctrl_transfer->context = xSemaphoreCreateBinary(); -} mock_cdc_dev_t; - /** * @brief Intended transfer response * diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/idf_component.yml b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/idf_component.yml similarity index 72% rename from host/class/cdc/usb_host_cdc_acm/host_test/main/idf_component.yml rename to host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/idf_component.yml index 528c8f3d..d72ab1a2 100644 --- a/host/class/cdc/usb_host_cdc_acm/host_test/main/idf_component.yml +++ b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/idf_component.yml @@ -2,4 +2,4 @@ dependencies: espressif/catch2: "^3.4.0" usb_host_cdc_acm: version: "*" - override_path: "../../" + override_path: "../../../" diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_device_interaction.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/test_device_interaction.cpp similarity index 89% rename from host/class/cdc/usb_host_cdc_acm/host_test/main/test_device_interaction.cpp rename to host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/test_device_interaction.cpp index 90387f4c..076d35eb 100644 --- a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_device_interaction.cpp +++ b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/test_device_interaction.cpp @@ -8,7 +8,6 @@ #include #include "cdc_descriptors.hpp" -#include "test_parsing_checker.hpp" #include "usb/cdc_acm_host.h" #include "mock_add_usb_device.h" #include "common_test_fixtures.hpp" @@ -17,12 +16,6 @@ extern "C" { #include "Mockusb_host.h" - -#include "Mockqueue.h" -#include "Mocktask.h" -#include "Mockidf_additions.h" -#include "Mockportmacro.h" -#include "Mockevent_groups.h" } /** @@ -70,11 +63,16 @@ static void _submit_mock_transfer(cdc_acm_dev_hdl_t *dev) { const uint8_t tx_buf[] = "HELLO"; // Submit transfer successfully - REQUIRE(ESP_OK == mock_cdc_acm_host_data_tx_blocking(*dev, tx_buf, sizeof(tx_buf), 1000, MOCK_USB_TRANSFER_SUCCESS)); + REQUIRE(ESP_OK == mock_cdc_acm_host_data_tx_blocking(*dev, tx_buf, sizeof(tx_buf), 200, MOCK_USB_TRANSFER_SUCCESS)); // Submit transfer which will fail to submit - REQUIRE(ESP_ERR_INVALID_RESPONSE == mock_cdc_acm_host_data_tx_blocking(*dev, tx_buf, sizeof(tx_buf), 1000, MOCK_USB_TRANSFER_ERROR)); + REQUIRE(ESP_ERR_INVALID_RESPONSE == mock_cdc_acm_host_data_tx_blocking(*dev, tx_buf, sizeof(tx_buf), 200, MOCK_USB_TRANSFER_ERROR)); // Submit transfer which times out - REQUIRE(ESP_ERR_TIMEOUT == mock_cdc_acm_host_data_tx_blocking(*dev, tx_buf, sizeof(tx_buf), 1000, MOCK_USB_TRANSFER_TIMEOUT)); + REQUIRE(ESP_ERR_TIMEOUT == mock_cdc_acm_host_data_tx_blocking(*dev, tx_buf, sizeof(tx_buf), 200, MOCK_USB_TRANSFER_TIMEOUT)); +} + +static void new_dev_cb(usb_device_handle_t usb_dev) +{ + printf("NEW DEVICE \n\n\n"); } @@ -91,7 +89,17 @@ SCENARIO("Interact with mocked USB devices") GIVEN("Mocked devices are added to the device list") { // Install CDC-ACM driver - REQUIRE(ESP_OK == mock_cdc_acm_host_install(nullptr)); + + usb_host_client_handle_events_IgnoreAndReturn(ESP_OK); + usb_host_client_handle_events_StopIgnore(); + + cdc_acm_host_driver_config_t driver_config = { + .driver_task_stack_size = 2048, + .driver_task_priority = 11, + .xCoreID = 0, + .new_dev_cb = new_dev_cb, + }; + REQUIRE(ESP_OK == mock_cdc_acm_host_install(&driver_config)); cdc_acm_dev_hdl_t dev = nullptr; const cdc_acm_host_device_config_t dev_config = { @@ -103,10 +111,6 @@ SCENARIO("Interact with mocked USB devices") .user_arg = nullptr, }; - // We can use this approach, in case the device opening and closing are not our DUT functions - - // Eg, in case we want to open a device, test something with the opened device open and close the device - // Test fixtures for seamless device opening and closing mock_cdc_acm_host_open(), mock_cdc_acm_host_close() SECTION("Interact with device: ASIX Electronics Corp. AX88772A Fast Ethernet") { // Define details of a device which will be opened diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/test_main.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/test_main.cpp new file mode 100644 index 00000000..c6130ffa --- /dev/null +++ b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/test_main.cpp @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + + +extern "C" void app_main(void) +{ + int argc = 1; + const char *argv[2] = { + "target_test_main", + NULL + }; + + auto result = Catch::Session().run(argc, argv); + if (result != 0) { + printf("Test failed with result %d\n", result); + } else { + printf("Test passed.\n"); + } + fflush(stdout); + exit(result); +} diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/test_opening_device.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/test_opening_device.cpp new file mode 100644 index 00000000..3333a970 --- /dev/null +++ b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/main/test_opening_device.cpp @@ -0,0 +1,123 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "cdc_descriptors.hpp" +#include "usb/cdc_acm_host.h" +#include "mock_add_usb_device.h" +#include "common_test_fixtures.hpp" + +extern "C" { +#include "Mockusb_host.h" +} + +/** + * @brief Add mocked devices + * + * Mocked devices are defined by a device descriptor, a configuration descriptor and a device address + */ +static void _add_mocked_devices(void) +{ + // Init mocked devices list at the beginning of the test + usb_host_mock_dev_list_init(); + + // Fill mocked devices list + // CP210x (FS descriptor) + REQUIRE(ESP_OK == usb_host_mock_add_device(5, (const usb_device_desc_t *)cp210x_device_desc, + (const usb_config_desc_t *)cp210x_config_desc)); +} + + +SCENARIO("Test mocked device opening and closing") +{ + // We will put device adding to the SECTION, to run it just once, not repeatedly for all the following SECTIONs + // (if multiple sections are present) + SECTION("Add mocked device") { + _add_mocked_devices(); + + // Optionally, print all the devices + // usb_host_mock_print_mocked_devices(0); + } + + SECTION("Fail to open CDC-ACM Device: CDC-ACM Host is not installed") { + REQUIRE(ESP_ERR_INVALID_STATE == cdc_acm_host_open(0, 0, 0, nullptr, nullptr)); + } + + GIVEN("Mocked device is added to the device list") { + // Install CDC-ACM driver + REQUIRE(ESP_OK == mock_cdc_acm_host_install(nullptr)); + + cdc_acm_dev_hdl_t dev = nullptr; + cdc_acm_host_device_config_t dev_config = { + .connection_timeout_ms = 1000, + .out_buffer_size = 100, + .in_buffer_size = 100, + .event_cb = nullptr, + .data_cb = nullptr, + .user_arg = nullptr, + }; + + // Define input parameters for cdc_acm_host_open + // VID, PID and interface number of the added cp120x device + const uint16_t vid = 0x10C4, pid = 0xEA60; + const uint8_t interface_number = 0; + + SECTION("Fail to open CDC-ACM Device: dev_config is nullptr") { + REQUIRE(ESP_ERR_INVALID_ARG == cdc_acm_host_open(vid, pid, interface_number, nullptr, &dev)); + } + + SECTION("Fail to open CDC-ACM Device: No devices found") { + dev_config.connection_timeout_ms = 1; // Set small connection timeout, so the usb_host_device_addr_list_fill() is called only once + int num_of_devices = 0; + usb_host_device_addr_list_fill_ExpectAnyArgsAndReturn(ESP_OK); + // Don't register callback to usb_host_device_addr_list_fill(), we want to use mocked function here + usb_host_device_addr_list_fill_ReturnThruPtr_num_dev_ret(&num_of_devices); + REQUIRE(ESP_ERR_NOT_FOUND == cdc_acm_host_open(vid, pid, interface_number, &dev_config, &dev)); + } + + AND_GIVEN("Fail to open CDC-ACM Device: No device with specified PID, VID, interface found") { + dev_config.connection_timeout_ms = 1; // Set small connection timeout, so the usb_host_device_addr_list_fill() is called only once + + // Fill address list with callback function + usb_host_device_addr_list_fill_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_device_addr_list_fill_AddCallback(usb_host_device_addr_list_fill_mock_callback); + + // Open device with callback function + usb_host_device_open_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_device_open_AddCallback(usb_host_device_open_mock_callback); + + usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_device_descriptor_AddCallback(usb_host_get_device_descriptor_mock_callback); + + usb_host_device_close_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_device_close_AddCallback(usb_host_device_close_mock_callback); + + SECTION("Incorrect VID") { + // A USB device present, but incorrect VID + REQUIRE(ESP_ERR_NOT_FOUND == cdc_acm_host_open(0x1234, pid, interface_number, &dev_config, &dev)); + } + + SECTION("Incorrect PID") { + // A USB device present, but incorrect VPID + REQUIRE(ESP_ERR_NOT_FOUND == cdc_acm_host_open(vid, 0x1234, interface_number, &dev_config, &dev)); + } + + SECTION("Incorrect Interface") { + usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_active_config_descriptor_ExpectAnyArgsAndReturn(ESP_OK); + usb_host_get_active_config_descriptor_AddCallback(usb_host_get_active_config_descriptor_mock_callback); + + // A USB device present, but incorrect interface + REQUIRE(ESP_ERR_NOT_FOUND == cdc_acm_host_open(vid, pid, 2, &dev_config, &dev)); + } + } + + // Uninstall CDC-ACM driver + REQUIRE(ESP_OK == mock_cdc_acm_host_uninstall()); + } +} diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/sdkconfig.defaults b/host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/sdkconfig.defaults similarity index 100% rename from host/class/cdc/usb_host_cdc_acm/host_test/sdkconfig.defaults rename to host/class/cdc/usb_host_cdc_acm/host_test/device_interaction/sdkconfig.defaults diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.cpp deleted file mode 100644 index b64fec75..00000000 --- a/host/class/cdc/usb_host_cdc_acm/host_test/main/common_test_fixtures.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -#include "cdc_descriptors.hpp" -#include "usb/cdc_acm_host.h" -#include "mock_add_usb_device.h" -#include "common_test_fixtures.hpp" -#include "esp_system.h" -#include "cdc_host_descriptor_parsing.h" - -extern "C" { -#include "Mockusb_host.h" - -#include "Mockqueue.h" -#include "Mocktask.h" -#include "Mockidf_additions.h" -#include "Mockportmacro.h" -#include "Mockevent_groups.h" -} - -mock_cdc_acm_obj_t *p_mock_cdc_acm_obj = nullptr; -mock_cdc_dev_t *p_mock_cdc_dev = nullptr; - -/** - * @brief Create CDC device object - * - * @param[in] dev_address Device address - * @param[in] interface_idx Interface index to be used - * @param[in] dev_config CDC-ACM Host device config struct - * - * @return - * - ESP_OK: Device created successfully - * - ESP_ERR_NO_MEM: Not enough memory - */ -static esp_err_t _create_cdc_dev(uint8_t dev_address, uint8_t interface_idx, const cdc_acm_host_device_config_t *dev_config) -{ - mock_cdc_dev_t *mock_cdc_dev = (mock_cdc_dev_t *)calloc(1, sizeof(mock_cdc_dev_t)); - if (mock_cdc_dev == nullptr) { - return ESP_ERR_NO_MEM; - } - - int notif_xfer, data_in_xfer, data_out_xfer; - const usb_config_desc_t *config_desc; - const usb_device_desc_t *device_desc; - cdc_parsed_info_t cdc_info; - int out_mux, out_sem, ctrl_mux, ctrl_sem; - usb_host_mock_get_config_descriptor_by_address(dev_address, &config_desc); - usb_host_mock_get_device_descriptor_by_address(dev_address, &device_desc); - cdc_parse_interface_descriptor(device_desc, config_desc, interface_idx, &cdc_info); - - // Get interface descriptors - mock_cdc_dev->data.intf_desc = cdc_info.data_intf; - mock_cdc_dev->notif.intf_desc = cdc_info.notif_intf; - // Get IN and OUT endpoints addresses - mock_cdc_dev->data.in_bEndpointAddress = cdc_info.in_ep->bEndpointAddress; - mock_cdc_dev->data.out_bEndpointAddress = cdc_info.out_ep->bEndpointAddress; - - // Get notification endpoint address and check if notification transfer is allocated (if notif. EP exists) - if (cdc_info.notif_ep) { - mock_cdc_dev->notif.bEndpointAddress = cdc_info.notif_ep->bEndpointAddress; - mock_cdc_dev->notif.xfer = reinterpret_cast(¬if_xfer); - } else { - mock_cdc_dev->notif.bEndpointAddress = 0; - mock_cdc_dev->notif.xfer = nullptr; - } - - // Check, if IN data transfer is allocated - if (dev_config->in_buffer_size) { - mock_cdc_dev->data.in_xfer = reinterpret_cast(&data_in_xfer); - } else { - mock_cdc_dev->data.in_xfer = nullptr; - } - - // Check if OUT data transfer is allocated - if (dev_config->out_buffer_size) { - mock_cdc_dev->data.out_xfer = reinterpret_cast(&data_out_xfer); - mock_cdc_dev->data.out_mux = reinterpret_cast(&out_mux); - mock_cdc_dev->data.out_sem = reinterpret_cast(&out_sem); - } else { - mock_cdc_dev->data.out_xfer = nullptr; - mock_cdc_dev->data.out_mux = nullptr; - mock_cdc_dev->data.out_sem = nullptr; - } - - mock_cdc_dev->ctrl_mux = reinterpret_cast(&ctrl_mux); - mock_cdc_dev->ctrl_sem = reinterpret_cast(&ctrl_sem); - - p_mock_cdc_dev = mock_cdc_dev; - return ESP_OK; -} - -/** - * @brief free space allocated for p_mock_cdc_dev - */ -static void _delete_cdc_dev(void) -{ - free(p_mock_cdc_dev); - p_mock_cdc_dev = nullptr; -} - -/** - * @brief Reset endpoint halt -> flush -> clear - * - * @param ep_address[in] Endpoint address to be reset - */ -static void _mock_cdc_acm_reset_transfer_endpoint(uint8_t ep_address) -{ - // Expect correct ep_address for all (halt, flush, clear) - usb_host_endpoint_halt_ExpectAndReturn(nullptr, ep_address, ESP_OK); - usb_host_endpoint_halt_IgnoreArg_dev_hdl(); - - usb_host_endpoint_flush_ExpectAndReturn(nullptr, ep_address, ESP_OK); - usb_host_endpoint_flush_IgnoreArg_dev_hdl(); - - usb_host_endpoint_clear_ExpectAndReturn(nullptr, ep_address, ESP_OK); - usb_host_endpoint_clear_IgnoreArg_dev_hdl(); -} - -esp_err_t mock_cdc_acm_host_install(const cdc_acm_host_driver_config_t *driver_config) -{ - vPortEnterCritical_Ignore(); // Ignore expecting vPortEnterCritical() - vPortExitCritical_Ignore(); // Ignore expecting vPortExitCritical() - - if (p_mock_cdc_acm_obj != nullptr) { - // CDC-ACM already installed - return ESP_ERR_INVALID_STATE; - } - - mock_cdc_acm_obj_t *mock_cdc_acm_obj = (mock_cdc_acm_obj_t *)calloc(1, sizeof(mock_cdc_acm_obj_t)); - if (mock_cdc_acm_obj == nullptr) { - return ESP_ERR_NO_MEM; - } - - int task_handle_ptr; - // Ensure task_handle is non nullptr, as it is used in ReturnThruPtr type of CMock function - TaskHandle_t task_handle = reinterpret_cast(&task_handle_ptr); - usb_host_client_handle_t client_handle = reinterpret_cast(&mock_cdc_acm_obj->cdc_acm_client_hdl); - // Create an EventGroup, return event group handle, so the EventGroup is created successfully - xEventGroupCreate_ExpectAndReturn(reinterpret_cast(&mock_cdc_acm_obj->event_group)); - // We should be calling xSemaphoreCreteMutex_ExpectAnyArgsAndRetrun instead of xQueueCreateMutex_ExpectAnyArgsAndReturn - // Because of missing Freertos Mocks - // Create a semaphore, return the semaphore handle (Queue Handle in this scenario), so the semaphore is created successfully - xQueueCreateMutex_ExpectAnyArgsAndReturn(reinterpret_cast(&mock_cdc_acm_obj->open_close_mutex)); - // Create a task, return pdTRUE, so the task is created successfully - xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdTRUE); - // Return task handle by pointer - xTaskCreatePinnedToCore_ReturnThruPtr_pxCreatedTask(&task_handle); - - // Call mocked function from USB Host - // return ESP_OK, so the client si registered successfully - usb_host_client_register_ExpectAnyArgsAndReturn(ESP_OK); - usb_host_client_register_ReturnThruPtr_client_hdl_ret(&client_handle); - - // Resume the task - vTaskResume_Expect(task_handle); - - p_mock_cdc_acm_obj = mock_cdc_acm_obj; - - // Call the real function cdc_acm_host_install() - return cdc_acm_host_install(driver_config); -} - -esp_err_t mock_cdc_acm_host_uninstall(void) -{ - vPortEnterCritical_Ignore(); // Ignore expecting vPortEnterCritical() - vPortExitCritical_Ignore(); // Ignore expecting vPortExitCritical() - - xQueueSemaphoreTake_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->open_close_mutex), portMAX_DELAY, pdTRUE); - - // Signal to CDC task to stop, unblock it and wait for its deletion - xEventGroupSetBits_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->event_group), BIT0, pdTRUE); - - // Call mocked function from USB Host - // return ESP_OK, so the client si unblocked successfully - usb_host_client_unblock_ExpectAnyArgsAndReturn(ESP_OK); - xEventGroupWaitBits_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->event_group), BIT1, pdFALSE, pdFALSE, pdMS_TO_TICKS(100), pdTRUE); - - // Free remaining resources - vEventGroupDelete_Expect(reinterpret_cast(&p_mock_cdc_acm_obj->event_group)); - xQueueGenericSend_ExpectAnyArgsAndReturn(pdTRUE); - vQueueDelete_Expect(reinterpret_cast(&p_mock_cdc_acm_obj->open_close_mutex)); - - free(p_mock_cdc_acm_obj); - p_mock_cdc_acm_obj = nullptr; - _delete_cdc_dev(); - - // Call the real function, cdc_acm_host_uninstall() - return cdc_acm_host_uninstall(); -} - -esp_err_t mock_cdc_acm_host_open(uint8_t dev_address, uint16_t vid, uint16_t pid, uint8_t interface_idx, const cdc_acm_host_device_config_t *dev_config, cdc_acm_dev_hdl_t *cdc_hdl_ret) -{ - vPortEnterCritical_Ignore(); // Ignore expecting vPortEnterCritical() - vPortExitCritical_Ignore(); // Ignore expecting vPortExitCritical() - - esp_err_t ret_create_dev = _create_cdc_dev(dev_address, interface_idx, dev_config); - if (ret_create_dev != ESP_OK) { - return ret_create_dev; // ESP_ERR_NO_MEM - } - - xQueueSemaphoreTake_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->open_close_mutex), portMAX_DELAY, pdTRUE); - vTaskSetTimeOutState_ExpectAnyArgs(); - - // Device opening - usb_host_device_addr_list_fill_ExpectAnyArgsAndReturn(ESP_OK); - usb_host_device_addr_list_fill_AddCallback(usb_host_device_addr_list_fill_callback); - - // We are expecting usb_host_device_open, usb_host_get_device_descriptor usb_host_device_close - // to be called at least mocked_devs_count times - const int mocked_devs_count = usb_host_mock_get_devs_count(); // Get number of mocked USB devices in mocked device list - for (int i = 0; i < mocked_devs_count; i++) { - usb_host_device_open_ExpectAnyArgsAndReturn(ESP_OK); - usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); - usb_host_device_close_ExpectAnyArgsAndReturn(ESP_OK); - } - - usb_host_device_open_AddCallback(usb_host_device_open_callback); - usb_host_get_device_descriptor_AddCallback(usb_host_get_device_descriptor_callback); - usb_host_device_close_AddCallback(usb_host_device_close_callback); - - // We have found the device by specified PID VID - - // Get Device and Configuration descriptors of the correct device - usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); - usb_host_get_active_config_descriptor_ExpectAnyArgsAndReturn(ESP_OK); - usb_host_get_active_config_descriptor_AddCallback(usb_host_get_active_config_descriptor_callback); - - // Setup control transfer - usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); - // Semaphore: cdc_dev->ctrl_transfer->context = xSemaphoreCreateBinary(); - xQueueGenericCreate_ExpectAnyArgsAndReturn(p_mock_cdc_dev->ctrl_sem); - // Mutex: cdc_dev->ctrl_mux = xSemaphoreCreateMutex(); - xQueueCreateMutex_ExpectAnyArgsAndReturn(p_mock_cdc_dev->ctrl_mux); - - // Setup Notif transfer - if (p_mock_cdc_dev->notif.xfer) { - usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); - } - - // Setup IN data transfer - if (dev_config->in_buffer_size) { - usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); - } - - // Setup OUT bulk transfer - if (dev_config->out_buffer_size) { - usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); - // Semaphore: cdc_dev->data.out_xfer->context = xSemaphoreCreateBinary(); - xQueueGenericCreate_ExpectAnyArgsAndReturn(p_mock_cdc_dev->data.out_sem); - // Mutex: cdc_dev->data.out_mux = xSemaphoreCreateMutex(); - xQueueCreateMutex_ExpectAnyArgsAndReturn(p_mock_cdc_dev->data.out_mux); - } - - // Register callback - usb_host_transfer_alloc_AddCallback(usb_host_transfer_alloc_callback); - - // Call cdc_acm_start - - // Claim data interface - // Make sure that the interface_idx has been claimed - usb_host_interface_claim_ExpectAndReturn(nullptr, nullptr, interface_idx, 0, ESP_OK); - usb_host_interface_claim_IgnoreArg_client_hdl(); // Ignore all function parameters, except interface_number - usb_host_interface_claim_IgnoreArg_dev_hdl(); - usb_host_interface_claim_IgnoreArg_bAlternateSetting(); - usb_host_transfer_submit_ExpectAnyArgsAndReturn(ESP_OK); - - // Claim notification interface (if supported) - if (p_mock_cdc_dev->notif.xfer) { - usb_host_interface_claim_ExpectAndReturn(nullptr, nullptr, interface_idx, 0, ESP_OK); - usb_host_interface_claim_IgnoreArg_client_hdl(); // Ignore all function parameters, except interface_number - usb_host_interface_claim_IgnoreArg_dev_hdl(); - usb_host_interface_claim_IgnoreArg_bAlternateSetting(); - usb_host_transfer_submit_ExpectAnyArgsAndReturn(ESP_OK); - } - - xQueueGenericSend_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->open_close_mutex), nullptr, 0, 0, pdTRUE); - xQueueGenericSend_IgnoreArg_pvItemToQueue(); - xQueueGenericSend_IgnoreArg_xCopyPosition(); - xQueueGenericSend_IgnoreArg_xTicksToWait(); - - // Call the real function cdc_acm_host_open - // Expect ESP_OK and dev_hdl non nullptr - esp_err_t ret = cdc_acm_host_open(vid, pid, interface_idx, dev_config, cdc_hdl_ret); - - // If the cdc_acm_host_open() fails, delete the created cdc_device - if (ret != ESP_OK) { - _delete_cdc_dev(); - } - return ret; -} - -esp_err_t mock_cdc_acm_host_close(cdc_acm_dev_hdl_t *cdc_hdl, uint8_t interface_number) -{ - vPortEnterCritical_Ignore(); // Ignore vPortEnterCritical() during this test case - vPortExitCritical_Ignore(); // Ignore vPortExitCritical() during this test case - - xQueueSemaphoreTake_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->open_close_mutex), portMAX_DELAY, pdTRUE); - - // Cancel pooling of IN endpoint -> halt, flush, clear - _mock_cdc_acm_reset_transfer_endpoint(p_mock_cdc_dev->data.in_bEndpointAddress); - - // Cancel pooling of Notification endpoint -> halt, flush, clear - if (p_mock_cdc_dev->notif.xfer) { - _mock_cdc_acm_reset_transfer_endpoint(p_mock_cdc_dev->notif.bEndpointAddress); - } - - // Release data interface - usb_host_interface_release_ExpectAndReturn(nullptr, nullptr, interface_number, ESP_OK); - usb_host_interface_release_IgnoreArg_client_hdl(); // Ignore all function parameters, except interface_number - usb_host_interface_release_IgnoreArg_dev_hdl(); - - - // Free notif transfer - if (p_mock_cdc_dev->notif.xfer) { - usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); - p_mock_cdc_dev->notif.xfer = nullptr; - } - - // Free in transfer - if (p_mock_cdc_dev->data.in_xfer) { - usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); - p_mock_cdc_dev->data.in_xfer = nullptr; - } - - // Free out transfer - if (p_mock_cdc_dev->data.out_xfer) { - usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); - vQueueDelete_Expect(p_mock_cdc_dev->data.out_sem); - vQueueDelete_Expect(p_mock_cdc_dev->data.out_mux); - p_mock_cdc_dev->data.out_xfer = nullptr; - } - - // Call cdc_acm_device_remove - // Free ctrl transfer - usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); - vQueueDelete_Expect(p_mock_cdc_dev->ctrl_sem); - vQueueDelete_Expect(p_mock_cdc_dev->ctrl_mux); - - usb_host_transfer_free_AddCallback(usb_host_transfer_free_callback); - - usb_host_device_close_ExpectAnyArgsAndReturn(ESP_OK); - - xQueueGenericSend_ExpectAndReturn(reinterpret_cast(&p_mock_cdc_acm_obj->open_close_mutex), nullptr, 0, 0, pdTRUE); - xQueueGenericSend_IgnoreArg_pvItemToQueue(); - xQueueGenericSend_IgnoreArg_xCopyPosition(); - xQueueGenericSend_IgnoreArg_xTicksToWait(); - - // Call the real function cdc_acm_host_close - return cdc_acm_host_close(*cdc_hdl); -} - -esp_err_t mock_cdc_acm_host_data_tx_blocking(cdc_acm_dev_hdl_t cdc_hdl, const uint8_t *data, size_t data_len, uint32_t timeout_ms, mock_usb_transfer_response_t transfer_response) -{ - vPortEnterCritical_Ignore(); // Ignore vPortEnterCritical() during this test case - vPortExitCritical_Ignore(); // Ignore vPortExitCritical() during this test case - - xQueueSemaphoreTake_ExpectAndReturn(p_mock_cdc_dev->data.out_mux, pdMS_TO_TICKS(timeout_ms), pdTRUE); - xQueueSemaphoreTake_ExpectAndReturn(p_mock_cdc_dev->data.out_sem, 0, pdTRUE); - usb_host_transfer_submit_ExpectAnyArgsAndReturn(ESP_OK); - - switch (transfer_response) { - case MOCK_USB_TRANSFER_SUCCESS: { - // Make the submitted transfer to pass - usb_host_transfer_submit_AddCallback(usb_host_transfer_submit_success_callback); - xQueueSemaphoreTake_ExpectAndReturn(p_mock_cdc_dev->data.out_sem, pdMS_TO_TICKS(timeout_ms), pdTRUE); - break; - } - case MOCK_USB_TRANSFER_ERROR: { - // Make the submitted transfer to fail - usb_host_transfer_submit_AddCallback(usb_host_transfer_submit_fail_callback); - xQueueSemaphoreTake_ExpectAndReturn(p_mock_cdc_dev->data.out_sem, pdMS_TO_TICKS(timeout_ms), pdTRUE); - break; - } - case MOCK_USB_TRANSFER_TIMEOUT: { - // Make the submitted transfer to be timed out - usb_host_transfer_submit_AddCallback(usb_host_transfer_submit_success_callback); - xQueueSemaphoreTake_ExpectAndReturn(p_mock_cdc_dev->data.out_sem, pdMS_TO_TICKS(timeout_ms), pdFALSE); - - // Reset out endpoint - _mock_cdc_acm_reset_transfer_endpoint(p_mock_cdc_dev->data.out_bEndpointAddress); - break; - } - default: - break; - } - - xQueueGenericSend_ExpectAndReturn(p_mock_cdc_dev->data.out_mux, 0, 0, 0, pdTRUE); - xQueueGenericSend_IgnoreArg_pvItemToQueue(); - xQueueGenericSend_IgnoreArg_xCopyPosition(); - xQueueGenericSend_IgnoreArg_xTicksToWait(); - - // Call the real function cdc_acm_host_data_tx_blocking() - return cdc_acm_host_data_tx_blocking(cdc_hdl, data, data_len, timeout_ms); -} diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_opening_device.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/main/test_opening_device.cpp deleted file mode 100644 index c1e4cf68..00000000 --- a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_opening_device.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#include "cdc_descriptors.hpp" -#include "test_parsing_checker.hpp" -#include "usb/cdc_acm_host.h" -#include "mock_add_usb_device.h" -#include "common_test_fixtures.hpp" -#include "usb_helpers.h" -#include "cdc_host_descriptor_parsing.h" - -extern "C" { -#include "Mockusb_host.h" - -#include "Mockqueue.h" -#include "Mocktask.h" -#include "Mockidf_additions.h" -#include "Mockportmacro.h" -#include "Mockevent_groups.h" -} - -/** - * @brief Add mocked devices - * - * Mocked devices are defined by a device descriptor, a configuration descriptor and a device address - */ -static void _add_mocked_devices(void) -{ - // Init mocked devices list at the beginning of the test - usb_host_mock_dev_list_init(); - - // Fill mocked devices list - // CP210x (FS descriptor) - REQUIRE(ESP_OK == usb_host_mock_add_device(5, (const usb_device_desc_t *)cp210x_device_desc, - (const usb_config_desc_t *)cp210x_config_desc)); -} - -/** - * @brief Open mocked device from mocked device list - * - * @note Device(s) must be firstly added to mocked device list by usb_host_mock_add_device() - * - * @param[in] vid VID of a device to be opened - * @param[in] pid PID of a device to be opened - * @param[in] interface_numer Interface number of a device to be opened - * @param[in] dev_config CDC-ACM device configuration - * @param[out] dev device handle - */ -static void _open_device(uint16_t vid, uint16_t pid, uint8_t interface_number, const cdc_acm_host_device_config_t *dev_config, cdc_acm_dev_hdl_t *dev) -{ - xQueueSemaphoreTake_ExpectAnyArgsAndReturn(pdTRUE); - vTaskSetTimeOutState_ExpectAnyArgs(); - - // Device opening - usb_host_device_addr_list_fill_ExpectAnyArgsAndReturn(ESP_OK); - usb_host_device_addr_list_fill_AddCallback(usb_host_device_addr_list_fill_callback); - - // We are expecting usb_host_device_open, usb_host_get_device_descriptor usb_host_device_close - // to be called at least mocked_devs_count times - // Get number of mocked USB devices in mocked device list - const int mocked_devs_count = usb_host_mock_get_devs_count(); - for (int i = 0; i < mocked_devs_count; i++) { - usb_host_device_open_ExpectAnyArgsAndReturn(ESP_OK); - usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); - usb_host_device_close_ExpectAnyArgsAndReturn(ESP_OK); - } - usb_host_device_open_AddCallback(usb_host_device_open_callback); - usb_host_get_device_descriptor_AddCallback(usb_host_get_device_descriptor_callback); - usb_host_device_close_AddCallback(usb_host_device_close_callback); - - // We have found the device by specified PID VID - - // Get Device and Configuration descriptors of the correct device - usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); - usb_host_get_active_config_descriptor_ExpectAnyArgsAndReturn(ESP_OK); - usb_host_get_active_config_descriptor_AddCallback(usb_host_get_active_config_descriptor_callback); - - // Call cdc_acm_transfer_allocate - int ctrl_transfer_semaphore, data_out_transfer_semaphore; - int ctrl_transfer_mutex, data_out_transfer_mutex; - - // Setup control transfer - usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); - // Semaphore: cdc_dev->ctrl_transfer->context = xSemaphoreCreateBinary(); - xQueueGenericCreate_ExpectAnyArgsAndReturn(reinterpret_cast(&ctrl_transfer_semaphore)); - // Mutex: cdc_dev->ctrl_mux = xSemaphoreCreateMutex(); - xQueueCreateMutex_ExpectAnyArgsAndReturn(reinterpret_cast(&ctrl_transfer_mutex)); - - // Setup IN data transfer - if (dev_config->in_buffer_size) { - usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); - } - - // Setup OUT bulk transfer - if (dev_config->out_buffer_size) { - usb_host_transfer_alloc_ExpectAnyArgsAndReturn(ESP_OK); - // Semaphore: cdc_dev->data.out_xfer->context = xSemaphoreCreateBinary(); - xQueueGenericCreate_ExpectAnyArgsAndReturn(reinterpret_cast(&data_out_transfer_semaphore)); - // Mutex: cdc_dev->data.out_mux = xSemaphoreCreateMutex(); - xQueueCreateMutex_ExpectAnyArgsAndReturn(reinterpret_cast(&data_out_transfer_mutex)); - } - - // Register callback - usb_host_transfer_alloc_AddCallback(usb_host_transfer_alloc_callback); - - // Call cdc_acm_start - // Make sure that the interface_number has been claimed - usb_host_interface_claim_ExpectAndReturn(nullptr, nullptr, interface_number, 0, ESP_OK); - usb_host_interface_claim_IgnoreArg_client_hdl(); - usb_host_interface_claim_IgnoreArg_dev_hdl(); - usb_host_interface_claim_IgnoreArg_bAlternateSetting(); - - usb_host_transfer_submit_ExpectAnyArgsAndReturn(ESP_OK); - xQueueGenericSend_ExpectAnyArgsAndReturn(pdTRUE); - - // Call the real DUT function cdc_acm_host_open() - // Expect ESP_OK and dev_hdl non nullptr - REQUIRE(ESP_OK == cdc_acm_host_open(vid, pid, interface_number, dev_config, dev)); - REQUIRE(dev != nullptr); -} - -/** - * @brief Just print the device and configuration descriptor of opened mocked device - * - * @note Device must be firstly opened by cdc_acm_host_open() - * - * @param[in] dev device handle - */ -static void _print_descriptor(cdc_acm_dev_hdl_t *dev) -{ - // Test that the mocked device was opened and can be used by the CDC-ACM host driver - usb_host_get_device_descriptor_ExpectAnyArgsAndReturn(ESP_OK); - usb_host_get_active_config_descriptor_ExpectAnyArgsAndReturn(ESP_OK); - - // Call DUT function cdc_acm_host_desc_print - // Expect device and configuration descriptors will be printed - cdc_acm_host_desc_print(*dev); -} - -/** - * @brief Close mocked device - * - * @note Device must be firstly opened by cdc_acm_host_open() - * - * @param[in] interface_numer Interface number of a device to be closed - * @param[in] dev_config CDC-ACM device configuration - * @param[out] dev device handle - */ -static void _close_device(uint8_t device_address, uint8_t interface_idx, const cdc_acm_host_device_config_t *dev_config, cdc_acm_dev_hdl_t *dev) -{ - // Get IN_EP address - const usb_config_desc_t *config_desc; - const usb_device_desc_t *device_desc; - cdc_parsed_info_t cdc_info; - usb_host_mock_get_config_descriptor_by_address(device_address, &config_desc); - usb_host_mock_get_device_descriptor_by_address(device_address, &device_desc); - cdc_parse_interface_descriptor(device_desc, config_desc, interface_idx, &cdc_info); - - xQueueSemaphoreTake_ExpectAnyArgsAndReturn(pdTRUE); - - // Cancel pooling of Interrupt IN endpoint -> halt, flush, clear - // Make sure to halt, flush, clear correct endpoints - usb_host_endpoint_halt_ExpectAndReturn(nullptr, cdc_info.in_ep->bEndpointAddress, ESP_OK); - usb_host_endpoint_halt_IgnoreArg_dev_hdl(); - - usb_host_endpoint_flush_ExpectAndReturn(nullptr, cdc_info.in_ep->bEndpointAddress, ESP_OK); - usb_host_endpoint_flush_IgnoreArg_dev_hdl(); - - usb_host_endpoint_clear_ExpectAndReturn(nullptr, cdc_info.in_ep->bEndpointAddress, ESP_OK); - usb_host_endpoint_clear_IgnoreArg_dev_hdl(); - - // Release data interface, make sure to release a correct interface - usb_host_interface_release_ExpectAndReturn(nullptr, nullptr, interface_idx, ESP_OK); - usb_host_interface_release_IgnoreArg_client_hdl(); - usb_host_interface_release_IgnoreArg_dev_hdl(); - - // Call cdc_acm_device_remove - // Free ctrl transfer - usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); - vQueueDelete_ExpectAnyArgs(); - vQueueDelete_ExpectAnyArgs(); - - // Free in transfer - if (dev_config->in_buffer_size) { - usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); - } - - // Free out transfer - if (dev_config->out_buffer_size) { - usb_host_transfer_free_ExpectAnyArgsAndReturn(ESP_OK); - vQueueDelete_ExpectAnyArgs(); - vQueueDelete_ExpectAnyArgs(); - } - usb_host_transfer_free_AddCallback(usb_host_transfer_free_callback); - - usb_host_device_close_ExpectAnyArgsAndReturn(ESP_OK); - xQueueGenericSend_ExpectAnyArgsAndReturn(pdTRUE); - - // Call the real DUT function cdc_acm_host_close() - // Expect ESP_OK - REQUIRE(ESP_OK == cdc_acm_host_close(*dev)); -} - -SCENARIO("Test mocked device opening and closing") -{ - // We will put device adding to the SECTION, to run it just once, not repeatedly for all the following SECTIONs - // (if multiple sections are present) - SECTION("Add mocked device") { - _add_mocked_devices(); - - // Optionally, print all the devices - //usb_host_mock_print_mocked_devices(0); - } - - GIVEN("Mocked device is added to the device list") { - // Install CDC-ACM driver - REQUIRE(ESP_OK == mock_cdc_acm_host_install(nullptr)); - - cdc_acm_dev_hdl_t dev = nullptr; - const cdc_acm_host_device_config_t dev_config = { - .connection_timeout_ms = 1000, - .out_buffer_size = 100, - .in_buffer_size = 100, - .event_cb = nullptr, - .data_cb = nullptr, - .user_arg = nullptr, - }; - - // We can use this approach, in case the device opening and closing are our DUT functions - // Eg, in case we want to test device opening and closing itself - SECTION("Test device opening and closing") { - - // Define input parameters for cdc_acm_host_open - const uint16_t vid = 0x10C4, pid = 0xEA60; - const uint8_t device_address = 5; - const uint8_t interface_number = 0; - - // ------------------------------------------ Open a device ------------------------------------------------ - _open_device(vid, pid, interface_number, &dev_config, &dev); - // ------------------------------------------ Get device info (use the device) ----------------------------- - _print_descriptor(&dev); - // ------------------------------------------ Close the device --------------------------------------------- - _close_device(device_address, interface_number, &dev_config, &dev); - } - - // Uninstall CDC-ACM driver - REQUIRE(ESP_OK == mock_cdc_acm_host_uninstall()); - } -} diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/CMakeLists.txt b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/CMakeLists.txt similarity index 100% rename from host/class/cdc/usb_host_cdc_acm/host_test/CMakeLists.txt rename to host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/CMakeLists.txt diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/README.md b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/README.md similarity index 93% rename from host/class/cdc/usb_host_cdc_acm/host_test/README.md rename to host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/README.md index be5808f2..0a770f35 100644 --- a/host/class/cdc/usb_host_cdc_acm/host_test/README.md +++ b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/README.md @@ -9,6 +9,7 @@ This directory contains test code for `USB Host CDC-ACM` driver. Namely: Tests are written using [Catch2](https://github.com/catchorg/Catch2) test framework, use CMock, so you must install Ruby on your machine to run them. +This test directory uses freertos as mocked component # Build Tests build regularly like an idf project. Currently only working on Linux machines. diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/CMakeLists.txt b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/CMakeLists.txt similarity index 72% rename from host/class/cdc/usb_host_cdc_acm/host_test/main/CMakeLists.txt rename to host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/CMakeLists.txt index 6fa86b66..be45a9a7 100644 --- a/host/class/cdc/usb_host_cdc_acm/host_test/main/CMakeLists.txt +++ b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/CMakeLists.txt @@ -1,7 +1,7 @@ idf_component_register(SRC_DIRS . REQUIRES cmock usb - INCLUDE_DIRS . - PRIV_INCLUDE_DIRS "../../private_include" + INCLUDE_DIRS "../../descriptors" . + PRIV_INCLUDE_DIRS "../../../private_include" WHOLE_ARCHIVE) # Currently 'main' for IDF_TARGET=linux is defined in freertos component. diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/idf_component.yml b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/idf_component.yml new file mode 100644 index 00000000..d72ab1a2 --- /dev/null +++ b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/idf_component.yml @@ -0,0 +1,5 @@ +dependencies: + espressif/catch2: "^3.4.0" + usb_host_cdc_acm: + version: "*" + override_path: "../../../" diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_parsing_checker.hpp b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/test_parsing_checker.hpp similarity index 100% rename from host/class/cdc/usb_host_cdc_acm/host_test/main/test_parsing_checker.hpp rename to host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/test_parsing_checker.hpp diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_parsing_ethernet_converters.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/test_parsing_ethernet_converters.cpp similarity index 100% rename from host/class/cdc/usb_host_cdc_acm/host_test/main/test_parsing_ethernet_converters.cpp rename to host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/test_parsing_ethernet_converters.cpp diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_parsing_modems.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/test_parsing_modems.cpp similarity index 100% rename from host/class/cdc/usb_host_cdc_acm/host_test/main/test_parsing_modems.cpp rename to host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/test_parsing_modems.cpp diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_parsing_tinyusb_devices.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/test_parsing_tinyusb_devices.cpp similarity index 100% rename from host/class/cdc/usb_host_cdc_acm/host_test/main/test_parsing_tinyusb_devices.cpp rename to host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/test_parsing_tinyusb_devices.cpp diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_parsing_uart_converters.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/test_parsing_uart_converters.cpp similarity index 100% rename from host/class/cdc/usb_host_cdc_acm/host_test/main/test_parsing_uart_converters.cpp rename to host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/test_parsing_uart_converters.cpp diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/main/test_unit_public_api.cpp b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/test_unit_public_api.cpp similarity index 100% rename from host/class/cdc/usb_host_cdc_acm/host_test/main/test_unit_public_api.cpp rename to host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/main/test_unit_public_api.cpp diff --git a/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/sdkconfig.defaults b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/sdkconfig.defaults new file mode 100644 index 00000000..14bc2aef --- /dev/null +++ b/host/class/cdc/usb_host_cdc_acm/host_test/parsing_tests/sdkconfig.defaults @@ -0,0 +1,8 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) 5.4.0 Project Minimal Configuration +# +CONFIG_IDF_TARGET="linux" +CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_ESP_MAIN_TASK_STACK_SIZE=12000 +CONFIG_FREERTOS_HZ=1000 +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n From c765ba26063d36a48ce363ba5d8888c4c5bdaf61 Mon Sep 17 00:00:00 2001 From: "peter.marcisovsky" Date: Thu, 28 Nov 2024 18:37:49 +0100 Subject: [PATCH 3/3] trigger CI