components/esp_eth/test_apps/README.md
| Supported Targets | ESP32 | ESP32-P4 |
|---|
This test app is used to test Ethernet MAC behavior with different chips.
Install third part Python packages:
pip install scapy
Different Ethernet chips may have deviations from the standard behavior or may not support certain features. To accommodate these chip-specific differences, the test framework provides Kconfig options that allow disabling or modifying specific tests that are incompatible with certain chips.
For example, some chips may not support 10 Mbps loopback mode, or may have known errata that require workarounds. These Kconfig options are defined in main/Kconfig.projbuild and can be configured through the ESP-IDF menuconfig system to adjust test behavior for the specific chip under test.
Refer to main/Kconfig.projbuild for the complete list of available configuration options and their descriptions.
The test framework provides common initialization and helper functions through esp_eth_test_utils.h and esp_eth_test_utils.c. These modules handle Ethernet initialization, event registration, and resource management automatically using Unity's setUp() and tearDown() functions.
The setUp() function automatically performs the following initialization before each test case:
esp_eth_test_eth_init() (uses Ethernet init component by default, can be customized - see Customizing Ethernet Initialization section below)[esp-netif] marker is used (see Markers section below)eth_test_default_event_handler() for ETH_EVENT events (ETHERNET_EVENT_START, ETHERNET_EVENT_STOP, ETHERNET_EVENT_CONNECTED, ETHERNET_EVENT_DISCONNECTED)eth_test_got_ip_event_handler() for IP_EVENT_ETH_GOT_IP events (only when [esp-netif] marker is used)The tearDown() function automatically performs cleanup after each test case:
esp_eth_test_eth_deinit() (uses Ethernet init component by default, can be customized - see Customizing Ethernet Initialization section below)By default, the test framework initializes Ethernet using the Ethernet init component. This provides initialization of Ethernet hardware based on Kconfig settings.
For test cases that require custom Ethernet initialization (e.g., chip not supported by Ethernet init component, specific MAC/PHY configurations, multiple Ethernet ports, or custom hardware setup), you can override the weak functions:
esp_eth_test_eth_init(esp_eth_handle_t *eth_handle): Override this function to provide custom Ethernet initialization. The function should initialize the Ethernet driver and return the handle via the eth_handle parameter.
[!IMPORTANT] Initialization function must print DUT PHY identification string as it is expected by
pytestscript. The PHY identification message must be in the following format:cprintf("DUT PHY: %s", my_phy_str);
esp_eth_test_eth_deinit(esp_eth_handle_t eth_handle): Override this function to provide custom Ethernet deinitialization. The function should clean up the Ethernet driver resources.
Test cases can use markers in their Unity test identifiers to control initialization behavior:
[esp-netif] MarkerWhen this marker is included in the test case identifier, setUp() will additionally initialize TCP/IP stack by:
ESP_NETIF_DEFAULT_ETH() configurationesp_eth_new_netif_glue()eth_test_got_ip_event_handler() for IP_EVENT_ETH_GOT_IP eventsExample:
TEST_CASE("ethernet dhcp test", "[ethernet][esp-netif]")
{
esp_eth_handle_t eth_handle = eth_test_get_eth_handle();
EventGroupHandle_t eth_event_group = eth_test_get_default_event_group();
esp_netif_t *netif = eth_test_get_netif(); // Valid when [esp-netif] is used
// Test code using TCP/IP stack...
}
[skip_setup_teardown] MarkerWhen this marker is included, setUp() and tearDown() will skip all automatic initialization and cleanup. This allows the test to perform its own custom initialization and cleanup procedures.
[!IMPORTANT] When using this marker, you must manually:
- Register event handlers using
eth_test_default_event_handler()and/oreth_test_got_ip_event_handler()- Initialize and deinitialize all resources except for memory allocated by
eth_test_alloc()
[!NOTE] Memory allocated through
eth_test_alloc()is automatically freed bytearDown()even when using this marker.
Example:
TEST_CASE("internal emac interrupt priority", "[esp_emac][skip_setup_teardown]")
{
// Manual initialization
EventGroupHandle_t eth_event_group = xEventGroupCreate();
TEST_ESP_OK(esp_event_loop_create_default());
// Register handlers manually if needed
// ... custom test code ...
}
eth_test_get_eth_handle(): Returns the Ethernet handle initialized by setUp(). Returns NULL if initialization failed or if [skip_setup_teardown] marker is used.eth_test_get_default_event_group(): Returns the event group handle created by setUp(). Use this to wait for Ethernet events using xEventGroupWaitBits() with the predefined bits (ETH_START_BIT, ETH_STOP_BIT, ETH_CONNECT_BIT, ETH_GOT_IP_BIT).eth_test_get_netif(): Returns the ESP-NETIF handle initialized by setUp(). Only valid when [esp-netif] marker is used, otherwise returns NULL.eth_test_set_phy_reg_bits(): Sets specific bits in a PHY register with retry logic. Useful for configuring PHY behavior during tests.eth_test_clear_phy_reg_bits(): Clears specific bits in a PHY register with retry logic.Both functions include automatic retry logic with configurable maximum attempts and delays between attempts.
eth_test_alloc(size): Allocates memory from the heap. The framework automatically tracks all allocations and frees them in tearDown(). Maximum of MAX_HEAP_ALLOCATION_POINTERS (20) allocations are supported.eth_test_free(ptr): Frees a specific allocation. Generally not needed as tearDown() automatically frees all tracked allocations.eth_test_free_all(): Frees all tracked allocations. Called automatically by tearDown().eth_test_default_event_handler(): Default handler for ETH_EVENT events. Automatically registered by setUp() unless [skip_setup_teardown] is used. Sets event bits in the event group for:
eth_test_got_ip_event_handler(): Handler for IP_EVENT_ETH_GOT_IP events. Automatically registered by setUp() when [esp-netif] marker is used. Sets ETH_GOT_IP_BIT in the event group and logs IP configuration.
TEST_CASE("ethernet basic test", "[ethernet][esp-netif]")
{
// Get handles initialized by setUp()
esp_eth_handle_t eth_handle = eth_test_get_eth_handle();
EventGroupHandle_t eth_event_group = eth_test_get_default_event_group();
esp_netif_t *netif = eth_test_get_netif();
EventBits_t bits = 0;
// Start Ethernet driver
TEST_ESP_OK(esp_eth_start(eth_handle));
// Wait for Ethernet to start
bits = xEventGroupWaitBits(eth_event_group, ETH_START_BIT, true, true,
pdMS_TO_TICKS(ETH_START_TIMEOUT_MS));
TEST_ASSERT((bits & ETH_START_BIT) == ETH_START_BIT);
// Wait for link connection
bits = xEventGroupWaitBits(eth_event_group, ETH_CONNECT_BIT, true, true,
pdMS_TO_TICKS(ETH_CONNECT_TIMEOUT_MS));
TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT);
// Wait for IP address (only when [esp-netif] is used)
bits = xEventGroupWaitBits(eth_event_group, ETH_GOT_IP_BIT, true, true,
pdMS_TO_TICKS(ETH_GET_IP_TIMEOUT_MS));
TEST_ASSERT((bits & ETH_GOT_IP_BIT) == ETH_GOT_IP_BIT);
// Test code here...
// Stop Ethernet driver
TEST_ESP_OK(esp_eth_stop(eth_handle));
// Wait for stop event
bits = xEventGroupWaitBits(eth_event_group, ETH_STOP_BIT, true, true,
pdMS_TO_TICKS(ETH_STOP_TIMEOUT_MS));
TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT);
// tearDown() will automatically clean up everything
}