From a7f002c37eb611fbc8ae074fa7db7963043ab8b5 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Wed, 10 Dec 2025 16:18:08 +0800 Subject: [PATCH] feat(esp_hw_support): add test case for esp_sleep_set_uart_handling --- .../main/CMakeLists.txt | 3 +- .../main/test_sleep_uart.c | 113 ++++++++++++++++++ .../pytest_esp_system_unity_tests.py | 51 ++++++++ 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep_uart.c diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/CMakeLists.txt b/components/esp_system/test_apps/esp_system_unity_tests/main/CMakeLists.txt index 5fad87dc660..4542a3dad06 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/CMakeLists.txt +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/CMakeLists.txt @@ -17,7 +17,8 @@ set(SRC "test_app_main.c" "test_task_wdt.c") if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED OR CONFIG_SOC_DEEP_SLEEP_SUPPORTED) - list(APPEND SRC "test_sleep.c") + list(APPEND SRC "test_sleep.c" + "test_sleep_uart.c") endif() if(CONFIG_SOC_SYSTIMER_SUPPORT_ETM) diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep_uart.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep_uart.c new file mode 100644 index 00000000000..d6379d52654 --- /dev/null +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep_uart.c @@ -0,0 +1,113 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "unity.h" +#include "esp_sleep.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "soc/soc_caps.h" + +/////////////////////////// UART Handling API Test Cases //////////////////////////////////// + +TEST_CASE("esp_sleep_set_console_uart_handling_mode parameter validation", "[sleep_uart]") +{ + // Test invalid handling mode + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_NO_HANDLING + 1)); + + // Test valid parameters + TEST_ASSERT_EQUAL(ESP_OK, esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_AUTO_FLUSH_SUSPEND_UART)); + TEST_ASSERT_EQUAL(ESP_OK, esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_ALWAYS_FLUSH_UART)); + TEST_ASSERT_EQUAL(ESP_OK, esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_ALWAYS_SUSPEND_UART)); + TEST_ASSERT_EQUAL(ESP_OK, esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_ALWAYS_DISCARD_UART)); + TEST_ASSERT_EQUAL(ESP_OK, esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_NO_HANDLING)); + + // Restore default + TEST_ASSERT_EQUAL(ESP_OK, esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_AUTO_FLUSH_SUSPEND_UART)); +} + +#if SOC_LIGHT_SLEEP_SUPPORTED + +/////////////////////////// pytest-based UART Output Verification Test Cases //////////////////////////////////// + +/* + * Test FLUSH mode: All data should be completely output before sleep + * pytest verifies: FLUSH_START -> all FLUSH_DATA_X -> FLUSH_SLEEP -> FLUSH_END + */ +TEST_CASE("UART flush mode output verification", "[sleep_uart_output]") +{ + TEST_ESP_OK(esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_ALWAYS_FLUSH_UART)); + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1000000)); // 1s + + printf("<<>>\n"); + for (int i = 0; i < 10; i++) { + printf("FLUSH_DATA_%d\n", i); + } + printf("<<>>\n"); + fflush(stdout); + + esp_light_sleep_start(); + + printf("<<>>\n"); + + TEST_ESP_OK(esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_AUTO_FLUSH_SUSPEND_UART)); +} + +/* + * Test SUSPEND mode: Data in TX FIFO should continue after wakeup + * pytest verifies: SUSPEND_START -> all SUSPEND_DATA_X -> SUSPEND_SLEEP -> SUSPEND_END + */ +TEST_CASE("UART suspend mode output verification", "[sleep_uart_output]") +{ + TEST_ESP_OK(esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_ALWAYS_SUSPEND_UART)); + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1000000)); // 1s + + printf("<<>>\n"); + for (int i = 0; i < 10; i++) { + printf("SUSPEND_DATA_%d\n", i); + } + printf("<<>>\n"); + fflush(stdout); + + esp_light_sleep_start(); + + printf("<<>>\n"); + + TEST_ESP_OK(esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_AUTO_FLUSH_SUSPEND_UART)); +} + +/* + * Test DISCARD mode: Data in TX FIFO should be discarded before sleep + * pytest verifies: DISCARD_START appears, DISCARD_END appears, + * but DISCARD_DATA_9_SHOULD_BE_LOST marker should NOT appear (data discarded) + */ +TEST_CASE("UART discard mode output verification", "[sleep_uart_output]") +{ + TEST_ESP_OK(esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_ALWAYS_DISCARD_UART)); + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1000000)); // 1s + + // This marker must be flushed to ensure it appears + printf("<<>>\n"); + fflush(stdout); + + // Print data without flush - this will stay in FIFO and be discarded + for (int i = 0; i < 10; i++) { + printf("DISCARD_DATA_%02d_SHOULD_BE_LOST\n", i); + } + // This marker should NOT appear because FIFO will be reset + printf("<<>>\n"); + fflush(stdout); + + esp_light_sleep_start(); + + // Small delay to ensure UART is stable after wakeup + vTaskDelay(pdMS_TO_TICKS(10)); + printf("<<>>\n"); + + TEST_ESP_OK(esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_AUTO_FLUSH_SUSPEND_UART)); +} + +#endif // SOC_LIGHT_SLEEP_SUPPORTED diff --git a/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py b/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py index 9882eb7ef0b..23357e18732 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py +++ b/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py @@ -1,5 +1,7 @@ # SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 +import time + import pytest from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize @@ -26,6 +28,55 @@ def test_esp_system(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=60) +def esp_reset_and_wait_ready(dut: Dut) -> None: + dut.serial.hard_reset() + time.sleep(0.5) + dut.expect_exact('Press ENTER to see the list of tests') + + +@pytest.mark.generic +@idf_parametrize('config', ['default'], indirect=['config']) +@idf_parametrize( + 'target', + [target for target in soc_filtered_targets('SOC_LIGHT_SLEEP_SUPPORTED == 1')], + indirect=['target'], +) +def test_sleep_uart_handling(dut: Dut) -> None: + """Test UART handling modes during light sleep.""" + # Test FLUSH mode output + esp_reset_and_wait_ready(dut) + dut.write('"UART flush mode output verification"') + dut.expect_exact('<<>>') + for i in range(10): + dut.expect_exact(f'FLUSH_DATA_{i}') + dut.expect_exact('<<>>') + dut.expect_exact('<<>>') + + # Test SUSPEND mode output - verify data continues after wakeup with sleep delay + esp_reset_and_wait_ready(dut) + dut.write('"UART suspend mode output verification"') + dut.expect_exact('<<>>') + start_time = time.time() + for i in range(10): + dut.expect_exact(f'SUSPEND_DATA_{i}') + dut.expect_exact('<<>>') + dut.expect_exact('<<>>') + end_time = time.time() + elapsed = end_time - start_time + # Sleep duration is 1 second, so total time should be >= 1s + assert elapsed >= 1.0, f'SUSPEND mode: expected >= 1s delay due to sleep, but got {elapsed:.2f}s' + + # Test DISCARD mode output - verify data is discarded + esp_reset_and_wait_ready(dut) + dut.write('"UART discard mode output verification"') + dut.expect_exact('<<>>') + # Capture output between START and END, verify DISCARD_DATA_9_SHOULD_BE_LOST is NOT present + output = dut.expect(r'<<>>', timeout=10) + assert '<<>>' not in output.group().decode(), ( + 'DISCARD mode failed: data should have been discarded but DISCARD_DATA_9_SHOULD_BE_LOST marker appeared' + ) + + @pytest.mark.generic @idf_parametrize('config', ['default'], indirect=['config']) @idf_parametrize('target', ['supported_targets'], indirect=['target'])