From cc9d354ba839ee6ebd9015374ed99bb9d9b1a9ff Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Mon, 28 Jun 2021 17:48:43 +0530 Subject: [PATCH] Update tests for assert and abort - Place panic_abort in IRAM - Added abort, assert test case in case of cache disabled - Expect assert instead of abort in a freertos_mutex test --- components/esp_system/panic.c | 2 +- .../freertos/test/test_freertos_mutex.c | 2 +- tools/test_apps/system/panic/app_test.py | 17 +++++++ .../system/panic/main/test_panic_main.c | 23 +++++++++ tools/test_apps/system/panic/panic_tests.py | 50 +++++++++++++++---- tools/unit-test-app/unit_test.py | 3 ++ 6 files changed, 86 insertions(+), 11 deletions(-) diff --git a/components/esp_system/panic.c b/components/esp_system/panic.c index 5c5b4f0d3d..b37f1cd3d0 100644 --- a/components/esp_system/panic.c +++ b/components/esp_system/panic.c @@ -362,7 +362,7 @@ void esp_panic_handler(panic_info_t *info) } -void __attribute__((noreturn)) panic_abort(const char *details) +void IRAM_ATTR __attribute__((noreturn)) panic_abort(const char *details) { g_panic_abort = true; s_panic_abort_details = (char*) details; diff --git a/components/freertos/test/test_freertos_mutex.c b/components/freertos/test/test_freertos_mutex.c index e4b68bb6a0..bd082c068a 100644 --- a/components/freertos/test/test_freertos_mutex.c +++ b/components/freertos/test/test_freertos_mutex.c @@ -14,7 +14,7 @@ static void mutex_release_task(void* arg) TEST_FAIL_MESSAGE("should not be reached"); } -TEST_CASE("mutex released not by owner causes an assert", "[freertos][reset=abort,SW_CPU_RESET]") +TEST_CASE("mutex released not by owner causes an assert", "[freertos][reset=assert,SW_CPU_RESET]") { SemaphoreHandle_t mutex = xSemaphoreCreateMutex(); xSemaphoreTake(mutex, portMAX_DELAY); diff --git a/tools/test_apps/system/panic/app_test.py b/tools/test_apps/system/panic/app_test.py index 971ed2a735..a6393c47d0 100644 --- a/tools/test_apps/system/panic/app_test.py +++ b/tools/test_apps/system/panic/app_test.py @@ -267,6 +267,11 @@ def test_panic_abort(env, _extra_data): test.abort_inner(env, 'panic') +@panic_test(target=['ESP32']) +def test_panic_abort_cache_disabled(env, _extra_data): + test.abort_cached_disabled_inner(env, 'panic') + + @panic_test() def test_coredump_abort_uart_elf_crc(env, _extra_data): test.abort_inner(env, 'coredump_uart_elf_crc') @@ -292,5 +297,17 @@ def test_gdbstub_abort(env, _extra_data): test.abort_inner(env, 'gdbstub') +# test_assert + +@panic_test(target=['ESP32', 'ESP32S2']) +def test_panic_assert(env, _extra_data): + test.assert_inner(env, 'panic') + + +@panic_test(target=['ESP32']) +def test_panic_assert_cache_disabled(env, _extra_data): + test.assert_cached_disabled_inner(env, 'panic') + + if __name__ == '__main__': run_all(__file__, sys.argv[1:]) diff --git a/tools/test_apps/system/panic/main/test_panic_main.c b/tools/test_apps/system/panic/main/test_panic_main.c index b7e42a1c3f..00a5cbc22d 100644 --- a/tools/test_apps/system/panic/main/test_panic_main.c +++ b/tools/test_apps/system/panic/main/test_panic_main.c @@ -14,6 +14,7 @@ static const char* get_test_name(void); /* functions which cause an exception/panic in different ways */ static void test_abort(void); +static void test_abort_cache_disabled(void); static void test_int_wdt(void); static void test_task_wdt(void); static void test_storeprohibited(void); @@ -22,6 +23,8 @@ static void test_int_wdt_cache_disabled(void); static void test_stack_overflow(void); static void test_illegal_instruction(void); static void test_instr_fetch_prohibited(void); +static void test_assert(void); +static void test_assert_cache_disabled(void); void app_main(void) @@ -44,6 +47,7 @@ void app_main(void) } HANDLE_TEST(test_abort); + HANDLE_TEST(test_abort_cache_disabled); HANDLE_TEST(test_int_wdt); HANDLE_TEST(test_task_wdt); HANDLE_TEST(test_storeprohibited); @@ -52,6 +56,8 @@ void app_main(void) HANDLE_TEST(test_stack_overflow); HANDLE_TEST(test_illegal_instruction); HANDLE_TEST(test_instr_fetch_prohibited); + HANDLE_TEST(test_assert); + HANDLE_TEST(test_assert_cache_disabled); #undef HANDLE_TEST @@ -65,6 +71,12 @@ static void test_abort(void) abort(); } +static void IRAM_ATTR test_abort_cache_disabled(void) +{ + esp_flash_default_chip->os_func->start(esp_flash_default_chip->os_func_data); + abort(); +} + static void test_int_wdt(void) { portDISABLE_INTERRUPTS(); @@ -100,6 +112,17 @@ static void IRAM_ATTR test_int_wdt_cache_disabled(void) } } +static void test_assert(void) +{ + assert(0); +} + +static void IRAM_ATTR test_assert_cache_disabled(void) +{ + esp_flash_default_chip->os_func->start(esp_flash_default_chip->os_func_data); + assert(0); +} + /** * This function overwrites the stack beginning from the valid area continuously towards and beyond * the end of the stack (stack base) of the current task. diff --git a/tools/test_apps/system/panic/panic_tests.py b/tools/test_apps/system/panic/panic_tests.py index fde69a5787..c890f4ae7d 100644 --- a/tools/test_apps/system/panic/panic_tests.py +++ b/tools/test_apps/system/panic/panic_tests.py @@ -51,11 +51,13 @@ def task_wdt_inner(env, test_name): dut.expect_backtrace() dut.expect_elf_sha256() dut.expect_none('Guru Meditation') - test_common(dut, test_name, expected_backtrace=[ - # Backtrace interrupted when abort is called, IDF-842. - # Task WDT calls abort internally. - 'panic_abort', 'esp_system_abort' - ]) + if ('gdbstub' in test_name): + test_common(dut, test_name, expected_backtrace=[ + # Backtrace interrupted when abort is called, IDF-842 + 'panic_abort', 'esp_system_abort' + ]) + else: + test_common(dut, test_name) def int_wdt_inner(env, test_name): @@ -103,10 +105,40 @@ def abort_inner(env, test_name): dut.expect_backtrace() dut.expect_elf_sha256() dut.expect_none('Guru Meditation', 'Re-entered core dump') - test_common(dut, test_name, expected_backtrace=[ - # Backtrace interrupted when abort is called, IDF-842 - 'panic_abort', 'esp_system_abort' - ]) + if ('gdbstub' in test_name): + test_common(dut, test_name, expected_backtrace=[ + # Backtrace interrupted when abort is called, IDF-842 + 'panic_abort', 'esp_system_abort' + ]) + else: + test_common(dut, test_name) + + +def abort_cached_disabled_inner(env, test_name): + with get_dut(env, test_name, 'test_abort_cache_disabled') as dut: + dut.expect(re.compile(r'abort\(\) was called at PC [0-9xa-f]+ on core 0')) + dut.expect_backtrace() + dut.expect_elf_sha256() + dut.expect_none('Guru Meditation', 'Re-entered core dump') + test_common(dut, test_name) + + +def assert_inner(env, test_name): + with get_dut(env, test_name, 'test_assert') as dut: + dut.expect(re.compile(r'(assert failed:[\s\w\(\)]*?\s[\.\w\/]*\.(?:c|cpp|h|hpp):\d*.*)')) + dut.expect_backtrace() + dut.expect_elf_sha256() + dut.expect_none('Guru Meditation', 'Re-entered core dump') + test_common(dut, test_name) + + +def assert_cached_disabled_inner(env, test_name): + with get_dut(env, test_name, 'test_assert_cache_disabled') as dut: + dut.expect(re.compile(r'(assert failed: [0-9xa-fA-F]+.*)')) + dut.expect_backtrace() + dut.expect_elf_sha256() + dut.expect_none('Guru Meditation', 'Re-entered core dump') + test_common(dut, test_name) def storeprohibited_inner(env, test_name): diff --git a/tools/unit-test-app/unit_test.py b/tools/unit-test-app/unit_test.py index bb5ee78887..7a69dbd63d 100755 --- a/tools/unit-test-app/unit_test.py +++ b/tools/unit-test-app/unit_test.py @@ -37,6 +37,7 @@ RESET_PATTERN = re.compile(r'(rst:0x[0-9a-fA-F]*\s\([\w].*?\),boot:0x[0-9a-fA-F] EXCEPTION_PATTERN = re.compile(r"(Guru Meditation Error: Core\s+\d panic'ed \([\w].*?\))") ABORT_PATTERN = re.compile(r'(abort\(\) was called at PC 0x[a-fA-F\d]{8} on core \d)') +ASSERT_PATTERN = re.compile(r'(assert failed: .*)') FINISH_PATTERN = re.compile(r'1 Tests (\d) Failures (\d) Ignored') END_LIST_STR = r'\r?\nEnter test for running' TEST_PATTERN = re.compile(r'\((\d+)\)\s+"([^"]+)" ([^\r\n]+)\r?\n(' + END_LIST_STR + r')?') @@ -268,6 +269,7 @@ def run_one_normal_case(dut, one_case, junit_test_case): dut.expect_any((RESET_PATTERN, handle_exception_reset), (EXCEPTION_PATTERN, handle_exception_reset), (ABORT_PATTERN, handle_exception_reset), + (ASSERT_PATTERN, handle_exception_reset), (FINISH_PATTERN, handle_test_finish), (UT_APP_BOOT_UP_DONE, handle_reset_finish), timeout=timeout_value) @@ -622,6 +624,7 @@ def run_one_multiple_stage_case(dut, one_case, junit_test_case): dut.expect_any((RESET_PATTERN, handle_exception_reset), (EXCEPTION_PATTERN, handle_exception_reset), (ABORT_PATTERN, handle_exception_reset), + (ASSERT_PATTERN, handle_exception_reset), (FINISH_PATTERN, handle_test_finish), (UT_APP_BOOT_UP_DONE, handle_next_stage), timeout=timeout_value)