2024-02-05 06:48:44 -05:00
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2022-02-11 01:58:50 -05:00
# SPDX-License-Identifier: CC0-1.0
import re
2024-02-27 17:51:28 -05:00
from typing import Any
2024-02-05 06:48:44 -05:00
from typing import List
from typing import Optional
2024-02-27 17:51:28 -05:00
from typing import Pattern
from typing import Sequence
2024-02-05 06:48:44 -05:00
from typing import Union
2022-02-11 01:58:50 -05:00
2022-12-02 11:30:56 -05:00
import pexpect
2022-02-11 01:58:50 -05:00
import pytest
2022-10-03 15:44:28 -04:00
from test_panic_util import PanicTestDut
2022-02-11 01:58:50 -05:00
2024-04-08 04:11:37 -04:00
TARGETS_XTENSA_SINGLE_CORE = [
2023-03-27 07:28:24 -04:00
pytest . mark . esp32s2 ,
2024-04-08 04:11:37 -04:00
]
TARGETS_XTENSA_DUAL_CORE = [
pytest . mark . esp32 ,
2023-03-27 07:28:24 -04:00
pytest . mark . esp32s3 ,
2024-04-08 04:11:37 -04:00
]
TARGETS_XTENSA = TARGETS_XTENSA_SINGLE_CORE + TARGETS_XTENSA_DUAL_CORE
TARGETS_RISCV_SINGLE_CORE = [
2023-03-27 07:28:24 -04:00
pytest . mark . esp32c2 ,
2024-04-08 04:11:37 -04:00
pytest . mark . esp32c3 ,
2023-03-27 07:28:24 -04:00
pytest . mark . esp32c6 ,
2024-01-19 02:51:57 -05:00
pytest . mark . esp32h2 ,
2024-04-08 04:11:37 -04:00
]
TARGETS_RISCV_DUAL_CORE = [
2024-01-19 02:51:57 -05:00
pytest . mark . esp32p4 ,
2023-03-27 07:28:24 -04:00
]
2022-12-01 08:00:50 -05:00
2024-04-08 04:11:37 -04:00
TARGETS_RISCV = TARGETS_RISCV_SINGLE_CORE + TARGETS_RISCV_DUAL_CORE
# Markers for all the targets this test currently runs on
TARGETS_ALL = TARGETS_XTENSA + TARGETS_RISCV
# Some tests only run on dual-core targets, they use the config below.
TARGETS_DUAL_CORE = TARGETS_XTENSA_DUAL_CORE + TARGETS_RISCV_DUAL_CORE
2022-12-01 08:00:50 -05:00
# Most tests run on all targets and with all configs.
# This list is passed to @pytest.mark.parametrize for each of the test cases.
# It creates an outer product of the sets: [configs] x [targets],
# with some exceptions.
2022-02-11 01:58:50 -05:00
CONFIGS = [
2024-04-08 04:11:37 -04:00
pytest . param ( ' coredump_flash_bin_crc ' , marks = TARGETS_ALL ) ,
pytest . param ( ' coredump_flash_elf_sha ' , marks = TARGETS_ALL ) ,
pytest . param ( ' coredump_uart_bin_crc ' , marks = TARGETS_ALL ) ,
pytest . param ( ' coredump_uart_elf_crc ' , marks = TARGETS_ALL ) ,
pytest . param ( ' coredump_flash_custom_stack ' , marks = TARGETS_RISCV ) ,
pytest . param ( ' gdbstub ' , marks = TARGETS_ALL ) ,
pytest . param ( ' panic ' , marks = TARGETS_ALL ) ,
2022-02-11 01:58:50 -05:00
]
2022-12-01 08:00:50 -05:00
CONFIGS_DUAL_CORE = [
pytest . param ( ' coredump_flash_bin_crc ' , marks = TARGETS_DUAL_CORE ) ,
2024-01-10 07:41:18 -05:00
pytest . param ( ' coredump_flash_elf_sha ' , marks = TARGETS_DUAL_CORE ) ,
2022-12-01 08:00:50 -05:00
pytest . param ( ' coredump_uart_bin_crc ' , marks = TARGETS_DUAL_CORE ) ,
pytest . param ( ' coredump_uart_elf_crc ' , marks = TARGETS_DUAL_CORE ) ,
pytest . param ( ' gdbstub ' , marks = TARGETS_DUAL_CORE ) ,
pytest . param ( ' panic ' , marks = TARGETS_DUAL_CORE ) ,
2022-07-15 07:38:23 -04:00
]
2022-12-01 08:00:50 -05:00
# Some tests run on all targets but need to behave differently on the dual-core ones.
# This list is used to check if the target is a dual-core one.
TARGETS_DUAL_CORE_NAMES = [ x . mark . name for x in TARGETS_DUAL_CORE ]
CONFIGS_EXTRAM_STACK = [
2024-05-02 18:00:03 -04:00
pytest . param ( ' coredump_flash_extram_stack_heap_esp32 ' , marks = [ pytest . mark . esp32 , pytest . mark . psram ] ) ,
pytest . param ( ' coredump_flash_extram_stack_heap_esp32s2 ' , marks = [ pytest . mark . esp32s2 , pytest . mark . generic ] ) ,
pytest . param ( ' coredump_flash_extram_stack_heap_esp32s3 ' , marks = [ pytest . mark . esp32s3 , pytest . mark . quad_psram ] ) ,
pytest . param ( ' coredump_flash_extram_stack_bss_esp32 ' , marks = [ pytest . mark . esp32 , pytest . mark . psram ] ) ,
pytest . param ( ' coredump_flash_extram_stack_bss_esp32s2 ' , marks = [ pytest . mark . esp32s2 , pytest . mark . generic ] ) ,
pytest . param ( ' coredump_flash_extram_stack_bss_esp32s3 ' , marks = [ pytest . mark . esp32s3 , pytest . mark . quad_psram ] ) ,
2022-12-19 11:38:17 -05:00
]
2023-05-04 11:31:31 -04:00
CONFIGS_HW_STACK_GUARD = [
2024-04-08 04:11:37 -04:00
pytest . param ( ' coredump_flash_bin_crc ' , marks = TARGETS_RISCV ) ,
pytest . param ( ' coredump_uart_bin_crc ' , marks = TARGETS_RISCV ) ,
pytest . param ( ' coredump_uart_elf_crc ' , marks = TARGETS_RISCV ) ,
pytest . param ( ' gdbstub ' , marks = TARGETS_RISCV ) ,
pytest . param ( ' panic ' , marks = TARGETS_RISCV ) ,
2023-05-04 11:31:31 -04:00
]
2024-01-19 02:51:57 -05:00
CONFIGS_HW_STACK_GUARD_DUAL_CORE = [
2024-04-08 04:11:37 -04:00
pytest . param ( ' coredump_flash_bin_crc ' , marks = TARGETS_RISCV_DUAL_CORE ) ,
pytest . param ( ' coredump_uart_bin_crc ' , marks = TARGETS_RISCV_DUAL_CORE ) ,
pytest . param ( ' coredump_uart_elf_crc ' , marks = TARGETS_RISCV_DUAL_CORE ) ,
pytest . param ( ' gdbstub ' , marks = TARGETS_RISCV_DUAL_CORE ) ,
pytest . param ( ' panic ' , marks = TARGETS_RISCV_DUAL_CORE ) ,
2024-01-19 02:51:57 -05:00
]
2024-03-11 16:19:17 -04:00
CONFIG_CAPTURE_DRAM = [ pytest . param ( ' coredump_flash_capture_dram ' , marks = TARGETS_ALL ) ]
2024-04-29 12:32:00 -04:00
CONFIG_COREDUMP_SUMMARY = [ pytest . param ( ' coredump_flash_elf_sha ' , marks = TARGETS_ALL ) ]
CONFIG_COREDUMP_SUMMARY_FLASH_ENCRYPTED = [
pytest . param ( ' coredump_flash_encrypted ' , marks = [ pytest . mark . esp32 , pytest . mark . esp32c3 ] ) ,
pytest . param ( ' coredump_flash_encrypted_coredump_plain ' , marks = [ pytest . mark . esp32 , pytest . mark . esp32c3 ] )
]
2023-08-03 17:47:58 -04:00
# Panic abort information will start with this string.
PANIC_ABORT_PREFIX = ' Panic reason: '
2022-02-11 01:58:50 -05:00
def get_default_backtrace ( config : str ) - > List [ str ] :
return [ config , ' app_main ' , ' main_task ' , ' vPortTaskWrapper ' ]
2023-08-03 17:47:58 -04:00
def common_test ( dut : PanicTestDut , config : str , expected_backtrace : Optional [ List [ str ] ] = None , check_cpu_reset : Optional [ bool ] = True ,
2024-02-27 17:51:28 -05:00
expected_coredump : Optional [ Sequence [ Union [ str , Pattern [ Any ] ] ] ] = None ) - > None :
2022-02-11 01:58:50 -05:00
if ' gdbstub ' in config :
dut . expect_exact ( ' Entering gdb stub now. ' )
2024-03-11 16:19:17 -04:00
dut . start_gdb_for_gdbstub ( )
2022-02-11 01:58:50 -05:00
frames = dut . gdb_backtrace ( )
2022-07-15 07:38:23 -04:00
if expected_backtrace is not None :
2022-12-01 08:00:50 -05:00
dut . verify_gdb_backtrace ( frames , expected_backtrace )
dut . revert_log_level ( )
return # don't expect "Rebooting" output below
2022-02-11 01:58:50 -05:00
2023-08-03 17:47:58 -04:00
# We will only perform comparisons for ELF files, as we are not introducing any new fields to the binary file format.
if ' bin ' in config :
expected_coredump = None
2022-02-11 01:58:50 -05:00
if ' uart ' in config :
2023-08-03 17:47:58 -04:00
dut . process_coredump_uart ( expected_coredump )
2022-02-11 01:58:50 -05:00
elif ' flash ' in config :
2023-08-03 17:47:58 -04:00
dut . process_coredump_flash ( expected_coredump )
2022-02-11 01:58:50 -05:00
elif ' panic ' in config :
pass
2024-08-15 10:16:54 -04:00
dut . expect ( ' Rebooting... ' , timeout = 60 )
2022-02-11 01:58:50 -05:00
2023-04-25 04:28:10 -04:00
if check_cpu_reset :
dut . expect_cpu_reset ( )
2022-02-11 01:58:50 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
@pytest.mark.generic
2022-07-15 07:38:23 -04:00
def test_task_wdt_cpu0 ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( test_func_name )
2022-02-11 01:58:50 -05:00
dut . expect_exact (
2022-05-24 22:30:29 -04:00
' Task watchdog got triggered. The following tasks/users did not reset the watchdog in time: '
2022-02-11 01:58:50 -05:00
)
dut . expect_exact ( ' CPU 0: main ' )
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
# on Xtensa, dumping registers on abort is not necessary, we only need to dump the backtrace
dut . expect_none ( ' register dump: ' )
dut . expect_exact ( ' Print CPU 0 (current core) backtrace ' )
dut . expect_backtrace ( )
else :
# on RISC-V, need to dump both registers and stack memory to reconstruct the backtrace
dut . expect_reg_dump ( core = 0 )
dut . expect_stack_dump ( )
2022-07-15 07:38:23 -04:00
dut . expect_elf_sha256 ( )
dut . expect_none ( ' Guru Meditation ' )
2023-11-09 03:10:43 -05:00
coredump_pattern = ( PANIC_ABORT_PREFIX +
' Task watchdog got triggered. '
' The following tasks/users did not reset the watchdog in time: \n - ' )
if dut . is_multi_core :
coredump_pattern + = ' IDLE0 (CPU 0) '
else :
coredump_pattern + = ' IDLE (CPU 0) '
2022-12-01 08:00:50 -05:00
common_test (
dut ,
config ,
expected_backtrace = get_default_backtrace ( test_func_name ) ,
2023-11-09 03:10:43 -05:00
expected_coredump = [ coredump_pattern ]
2022-12-01 08:00:50 -05:00
)
2022-07-15 07:38:23 -04:00
2022-12-01 08:00:50 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_DUAL_CORE , indirect = True )
2022-07-15 07:38:23 -04:00
@pytest.mark.generic
def test_task_wdt_cpu1 ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( test_func_name )
2022-07-15 07:38:23 -04:00
dut . expect_exact (
' Task watchdog got triggered. The following tasks/users did not reset the watchdog in time: '
)
dut . expect_exact ( ' CPU 1: Infinite loop ' )
2024-01-19 02:51:57 -05:00
expected_backtrace = [ ' infinite_loop ' , ' vPortTaskWrapper ' ]
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
# see comment in test_task_wdt_cpu0
dut . expect_none ( ' register dump: ' )
dut . expect_exact ( ' Print CPU 1 backtrace ' )
dut . expect_backtrace ( )
else :
2024-01-19 02:51:57 -05:00
# on RISC-V, need to dump both registers and stack memory to reconstruct the backtrace
dut . expect_reg_dump ( core = 1 )
dut . expect_stack_dump ( )
2022-12-01 08:00:50 -05:00
2022-07-15 07:38:23 -04:00
dut . expect_elf_sha256 ( )
dut . expect_none ( ' Guru Meditation ' )
2023-11-09 03:10:43 -05:00
coredump_pattern = ( PANIC_ABORT_PREFIX +
' Task watchdog got triggered. '
' The following tasks/users did not reset the watchdog in time: \n - IDLE1 (CPU 1) ' )
2022-12-01 08:00:50 -05:00
common_test (
dut ,
config ,
expected_backtrace = expected_backtrace ,
2023-11-09 03:10:43 -05:00
expected_coredump = [ coredump_pattern ]
2022-12-01 08:00:50 -05:00
)
2022-07-15 07:38:23 -04:00
2022-12-01 08:00:50 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_EXTRAM_STACK , indirect = True )
2024-05-02 18:00:03 -04:00
def test_panic_extram_stack ( dut : PanicTestDut , config : str ) - > None :
if ' heap ' in config :
dut . run_test_func ( ' test_panic_extram_stack_heap ' )
else :
dut . run_test_func ( ' test_panic_extram_stack_bss ' )
2022-12-19 11:38:17 -05:00
dut . expect_none ( ' Allocated stack is not in external RAM ' )
dut . expect_none ( ' Guru Meditation ' )
dut . expect_backtrace ( )
dut . expect_elf_sha256 ( )
# Check that coredump is getting written to flash
dut . expect_exact ( ' Save core dump to flash... ' )
# And that the stack is replaced and restored
dut . expect_exact ( ' Backing up stack @ ' )
dut . expect_exact ( ' Restoring stack ' )
# The caller must be accessible after restoring the stack
dut . expect_exact ( ' Core dump has been saved to flash. ' )
2023-04-25 04:28:10 -04:00
2024-05-02 18:00:03 -04:00
if dut . target == ' esp32 ' :
# ESP32 External data memory range [0x3f800000-0x3fc00000)
coredump_pattern = re . compile ( ' .coredump.tasks.data (0x3[fF][8-9a-bA-B][0-9a-fA-F] {5} ) (0x[a-fA-F0-9]+) RW ' )
elif dut . target == ' esp32s2 ' :
# ESP32-S2 External data memory range [0x3f500000-0x3ff80000)
coredump_pattern = re . compile ( ' .coredump.tasks.data (0x3[fF][5-9a-fA-F][0-7][0-9a-fA-F] {4} ) (0x[a-fA-F0-9]+) RW ' )
else :
# ESP32-S3 External data memory range [0x3c000000-0x3e000000)
coredump_pattern = re . compile ( ' .coredump.tasks.data (0x3[c-dC-D][0-9a-fA-F] {6} ) (0x[a-fA-F0-9]+) RW ' )
common_test (
dut ,
config ,
expected_backtrace = None ,
expected_coredump = [ coredump_pattern ]
)
2022-12-19 11:38:17 -05:00
2022-02-11 01:58:50 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
@pytest.mark.generic
def test_int_wdt (
dut : PanicTestDut , target : str , config : str , test_func_name : str
) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( test_func_name )
2022-02-11 01:58:50 -05:00
dut . expect_gme ( ' Interrupt wdt timeout on CPU0 ' )
dut . expect_reg_dump ( 0 )
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
else :
dut . expect_stack_dump ( )
2022-02-11 01:58:50 -05:00
2022-12-01 08:00:50 -05:00
if target in TARGETS_DUAL_CORE_NAMES :
2022-02-11 01:58:50 -05:00
dut . expect_reg_dump ( 1 )
2024-01-19 02:51:57 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
2022-12-01 08:00:50 -05:00
dut . expect_elf_sha256 ( )
dut . expect_none ( ' Guru Meditation ' )
2022-02-11 01:58:50 -05:00
common_test ( dut , config , expected_backtrace = get_default_backtrace ( test_func_name ) )
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
@pytest.mark.generic
def test_int_wdt_cache_disabled (
dut : PanicTestDut , target : str , config : str , test_func_name : str
) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( test_func_name )
2022-02-11 01:58:50 -05:00
dut . expect_gme ( ' Interrupt wdt timeout on CPU0 ' )
dut . expect_reg_dump ( 0 )
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
else :
dut . expect_stack_dump ( )
2022-02-11 01:58:50 -05:00
2022-12-01 08:00:50 -05:00
if target in TARGETS_DUAL_CORE_NAMES :
2022-02-11 01:58:50 -05:00
dut . expect_reg_dump ( 1 )
2024-01-19 02:51:57 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
2022-12-01 08:00:50 -05:00
dut . expect_elf_sha256 ( )
dut . expect_none ( ' Guru Meditation ' )
2022-02-11 01:58:50 -05:00
common_test ( dut , config , expected_backtrace = get_default_backtrace ( test_func_name ) )
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
@pytest.mark.generic
def test_cache_error ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( test_func_name )
2023-11-27 20:57:44 -05:00
if dut . target in [ ' esp32c3 ' , ' esp32c2 ' ] :
dut . expect_gme ( ' Cache error ' )
dut . expect_exact ( ' Cached memory region accessed while ibus or cache is disabled ' )
2022-12-01 08:00:50 -05:00
elif dut . target in [ ' esp32s2 ' ] :
# Cache error interrupt is not enabled, IDF-1558
dut . expect_gme ( ' IllegalInstruction ' )
2024-08-05 03:03:10 -04:00
elif dut . target in [ ' esp32 ' , ' esp32s3 ' ] :
2022-12-01 08:00:50 -05:00
dut . expect_gme ( ' Cache disabled but cached memory region accessed ' )
2024-08-05 03:03:10 -04:00
else :
dut . expect_gme ( ' Cache error ' )
dut . expect_exact ( ' Cache access error ' )
2022-02-11 01:58:50 -05:00
dut . expect_reg_dump ( 0 )
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
else :
dut . expect_stack_dump ( )
2022-02-11 01:58:50 -05:00
dut . expect_elf_sha256 ( )
dut . expect_none ( ' Guru Meditation ' )
2022-12-01 08:00:50 -05:00
expected_backtrace = [ ' die ' ] + get_default_backtrace ( test_func_name )
if dut . target in [ ' esp32s2 ' , ' esp32s3 ' ] :
# 'test_cache_error' missing from GDB backtrace on ESP32-S2 and ESP-S3, IDF-6561
expected_backtrace = [ ' die ' , ' app_main ' , ' main_task ' , ' vPortTaskWrapper ' ]
2023-04-25 04:28:10 -04:00
2022-02-11 01:58:50 -05:00
common_test (
2023-04-25 04:28:10 -04:00
dut , config , expected_backtrace = expected_backtrace , check_cpu_reset = ( dut . target != ' esp32 ' )
2022-02-11 01:58:50 -05:00
)
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
@pytest.mark.generic
def test_stack_overflow ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( test_func_name )
if dut . is_xtensa :
dut . expect_gme ( ' Unhandled debug exception ' )
dut . expect_exact ( ' Stack canary watchpoint triggered (main) ' )
else :
# Stack watchpoint handling missing on RISC-V, IDF-6397
dut . expect_gme ( ' Breakpoint ' )
2022-02-11 01:58:50 -05:00
dut . expect_reg_dump ( 0 )
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
else :
dut . expect_stack_dump ( )
2022-02-11 01:58:50 -05:00
dut . expect_elf_sha256 ( )
dut . expect_none ( ' Guru Meditation ' )
2023-04-25 04:28:10 -04:00
2022-02-11 01:58:50 -05:00
common_test ( dut , config , expected_backtrace = get_default_backtrace ( test_func_name ) )
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
@pytest.mark.generic
def test_instr_fetch_prohibited (
dut : PanicTestDut , config : str , test_func_name : str
) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( test_func_name )
if dut . is_xtensa :
dut . expect_gme ( ' InstrFetchProhibited ' )
dut . expect_reg_dump ( 0 )
dut . expect_backtrace ( )
expected_backtrace = [ ' _init ' ] + get_default_backtrace ( test_func_name )
else :
dut . expect_gme ( ' Instruction access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
# On RISC-V, GDB is not able to determine the correct backtrace after
# a jump to an invalid address.
expected_backtrace = [ ' ?? ' ]
2022-02-11 01:58:50 -05:00
dut . expect_elf_sha256 ( )
dut . expect_none ( ' Guru Meditation ' )
2023-04-25 04:28:10 -04:00
2022-02-11 01:58:50 -05:00
common_test (
dut ,
config ,
2022-12-01 08:00:50 -05:00
expected_backtrace = expected_backtrace ,
2022-02-11 01:58:50 -05:00
)
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
@pytest.mark.generic
def test_illegal_instruction (
dut : PanicTestDut , config : str , test_func_name : str
) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( test_func_name )
if dut . is_xtensa :
dut . expect_gme ( ' IllegalInstruction ' )
else :
dut . expect_gme ( ' Illegal instruction ' )
2022-02-11 01:58:50 -05:00
dut . expect_reg_dump ( 0 )
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
else :
dut . expect_stack_dump ( )
2022-02-11 01:58:50 -05:00
dut . expect_elf_sha256 ( )
dut . expect_none ( ' Guru Meditation ' )
2023-04-25 04:28:10 -04:00
2022-02-11 01:58:50 -05:00
common_test ( dut , config , expected_backtrace = get_default_backtrace ( test_func_name ) )
2024-04-15 11:09:11 -04:00
def check_x_prohibited ( dut : PanicTestDut , config : str , test_func_name : str , operation : str ) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( test_func_name )
if dut . is_xtensa :
2024-04-15 11:09:11 -04:00
dut . expect_gme ( f ' { operation } Prohibited ' )
2022-12-01 08:00:50 -05:00
else :
2024-04-15 11:09:11 -04:00
dut . expect_gme ( f ' { operation } access fault ' )
2022-02-11 01:58:50 -05:00
dut . expect_reg_dump ( 0 )
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
else :
dut . expect_stack_dump ( )
2022-02-11 01:58:50 -05:00
dut . expect_elf_sha256 ( )
dut . expect_none ( ' Guru Meditation ' )
2023-04-25 04:28:10 -04:00
2022-02-11 01:58:50 -05:00
common_test ( dut , config , expected_backtrace = get_default_backtrace ( test_func_name ) )
2024-04-15 11:09:11 -04:00
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
@pytest.mark.generic
def test_storeprohibited ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
check_x_prohibited ( dut , config , test_func_name , ' Store ' )
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
@pytest.mark.generic
def test_loadprohibited ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
check_x_prohibited ( dut , config , test_func_name , ' Load ' )
2022-02-11 01:58:50 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
@pytest.mark.generic
def test_abort ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( test_func_name )
2023-08-03 17:47:58 -04:00
regex_pattern = rb ' abort \ ( \ ) was called at PC [0-9xa-f]+ on core 0 '
dut . expect ( regex_pattern )
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
else :
dut . expect_stack_dump ( )
2022-02-11 01:58:50 -05:00
dut . expect_elf_sha256 ( )
dut . expect_none ( [ ' Guru Meditation ' , ' Re-entered core dump ' ] )
2023-08-03 17:47:58 -04:00
coredump_pattern = re . compile ( PANIC_ABORT_PREFIX + regex_pattern . decode ( ' utf-8 ' ) )
2022-12-01 08:00:50 -05:00
common_test (
dut ,
config ,
expected_backtrace = [
' panic_abort ' ,
' esp_system_abort ' ,
' abort '
] + get_default_backtrace ( test_func_name ) ,
2023-08-03 17:47:58 -04:00
expected_coredump = [ coredump_pattern ]
2022-12-01 08:00:50 -05:00
)
2022-02-11 01:58:50 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
@pytest.mark.generic
def test_ub ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( test_func_name )
2023-08-03 17:47:58 -04:00
regex_pattern = rb ' Undefined behavior of type out_of_bounds '
dut . expect ( regex_pattern )
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
else :
dut . expect_stack_dump ( )
2022-02-11 01:58:50 -05:00
dut . expect_elf_sha256 ( )
dut . expect_none ( [ ' Guru Meditation ' , ' Re-entered core dump ' ] )
2023-08-03 17:47:58 -04:00
coredump_pattern = re . compile ( PANIC_ABORT_PREFIX + regex_pattern . decode ( ' utf-8 ' ) )
2022-12-01 08:00:50 -05:00
common_test (
dut ,
config ,
expected_backtrace = [
' panic_abort ' ,
' esp_system_abort ' ,
' __ubsan_default_handler ' ,
' __ubsan_handle_out_of_bounds '
] + get_default_backtrace ( test_func_name ) ,
2023-08-03 17:47:58 -04:00
expected_coredump = [ coredump_pattern ]
2022-12-01 08:00:50 -05:00
)
2022-02-11 01:58:50 -05:00
2022-12-01 08:00:50 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
2022-02-11 01:58:50 -05:00
@pytest.mark.generic
def test_abort_cache_disabled (
dut : PanicTestDut , config : str , test_func_name : str
) - > None :
2022-12-01 08:00:50 -05:00
if dut . target == ' esp32s2 ' :
pytest . xfail ( reason = ' Crashes in itoa which is not in ROM, IDF-3572 ' )
dut . run_test_func ( test_func_name )
2023-08-03 17:47:58 -04:00
regex_pattern = rb ' abort \ ( \ ) was called at PC [0-9xa-f]+ on core 0 '
dut . expect ( regex_pattern )
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
else :
dut . expect_stack_dump ( )
2022-02-11 01:58:50 -05:00
dut . expect_elf_sha256 ( )
dut . expect_none ( [ ' Guru Meditation ' , ' Re-entered core dump ' ] )
2023-04-25 04:28:10 -04:00
2023-08-03 17:47:58 -04:00
coredump_pattern = re . compile ( PANIC_ABORT_PREFIX + regex_pattern . decode ( ' utf-8 ' ) )
2022-12-01 08:00:50 -05:00
common_test (
dut ,
config ,
expected_backtrace = [
' panic_abort ' ,
' esp_system_abort ' ,
' abort '
] + get_default_backtrace ( test_func_name ) ,
2023-08-03 17:47:58 -04:00
expected_coredump = [ coredump_pattern ]
2022-12-01 08:00:50 -05:00
)
2022-02-11 01:58:50 -05:00
2022-12-01 08:00:50 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
2022-02-11 01:58:50 -05:00
@pytest.mark.generic
def test_assert ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( test_func_name )
2023-08-03 17:47:58 -04:00
regex_pattern = rb ' assert failed:[ \ s \ w()]*? \ s[. \ w/]* \ .(?:c|cpp|h|hpp): \ d.*$ '
dut . expect ( re . compile ( regex_pattern , re . MULTILINE ) )
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
else :
dut . expect_stack_dump ( )
2022-02-11 01:58:50 -05:00
dut . expect_elf_sha256 ( )
dut . expect_none ( [ ' Guru Meditation ' , ' Re-entered core dump ' ] )
2023-08-03 17:47:58 -04:00
coredump_pattern = re . compile ( PANIC_ABORT_PREFIX + regex_pattern . decode ( ' utf-8 ' ) , re . MULTILINE )
2022-12-01 08:00:50 -05:00
common_test (
dut ,
config ,
expected_backtrace = [
' panic_abort ' ,
' esp_system_abort ' ,
' __assert_func '
2023-08-03 17:47:58 -04:00
] + get_default_backtrace ( test_func_name ) ,
expected_coredump = [ coredump_pattern ]
)
2022-02-11 01:58:50 -05:00
2022-12-01 08:00:50 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS , indirect = True )
2022-02-11 01:58:50 -05:00
@pytest.mark.generic
def test_assert_cache_disabled (
dut : PanicTestDut , config : str , test_func_name : str
) - > None :
2022-12-01 08:00:50 -05:00
if dut . target == ' esp32s2 ' :
pytest . xfail ( reason = ' Crashes in itoa which is not in ROM, IDF-3572 ' )
dut . run_test_func ( test_func_name )
2023-08-03 17:47:58 -04:00
regex_pattern = rb ' assert failed: [0-9xa-fA-F]+.*$ '
dut . expect ( re . compile ( regex_pattern , re . MULTILINE ) )
2022-12-01 08:00:50 -05:00
if dut . is_xtensa :
dut . expect_backtrace ( )
else :
dut . expect_stack_dump ( )
2022-02-11 01:58:50 -05:00
dut . expect_elf_sha256 ( )
dut . expect_none ( [ ' Guru Meditation ' , ' Re-entered core dump ' ] )
2023-04-25 04:28:10 -04:00
2023-08-03 17:47:58 -04:00
coredump_pattern = re . compile ( PANIC_ABORT_PREFIX + regex_pattern . decode ( ' utf-8 ' ) , re . MULTILINE )
2022-12-01 08:00:50 -05:00
common_test (
dut ,
config ,
expected_backtrace = [
' panic_abort ' ,
' esp_system_abort ' ,
' __assert_func '
2023-08-03 17:47:58 -04:00
] + get_default_backtrace ( test_func_name ) ,
expected_coredump = [ coredump_pattern ]
)
2022-12-02 11:30:56 -05:00
2024-04-25 12:13:46 -04:00
def cache_error_log_check ( dut : PanicTestDut ) - > None :
if dut . is_xtensa :
if dut . target == ' esp32s3 ' :
dut . expect_exact ( " Guru Meditation Error: Core / panic ' ed (Cache disabled but cached memory region accessed) " )
dut . expect_exact ( ' Write back error occurred while dcache tries to write back to flash ' )
dut . expect_exact ( ' The following backtrace may not indicate the code that caused Cache invalid access ' )
else :
dut . expect_exact ( " Guru Meditation Error: Core 0 panic ' ed (LoadStoreError) " )
else :
dut . expect_exact ( " Guru Meditation Error: Core 0 panic ' ed (Store access fault) " )
dut . expect_reg_dump ( 0 )
if dut . target == ' esp32s3 ' :
dut . expect_reg_dump ( 1 )
dut . expect_cpu_reset ( )
@pytest.mark.generic
@pytest.mark.supported_targets
@pytest.mark.parametrize ( ' config ' , [ ' panic ' ] , indirect = True )
def test_assert_cache_write_back_error_can_print_backtrace (
dut : PanicTestDut , config : str , test_func_name : str
) - > None :
dut . run_test_func ( test_func_name )
cache_error_log_check ( dut )
@pytest.mark.generic
@pytest.mark.supported_targets
@pytest.mark.parametrize ( ' config ' , [ ' panic ' ] , indirect = True )
def test_assert_cache_write_back_error_can_print_backtrace2 (
dut : PanicTestDut , config : str , test_func_name : str
) - > None :
dut . run_test_func ( test_func_name )
cache_error_log_check ( dut )
2022-12-02 11:30:56 -05:00
@pytest.mark.esp32
2024-04-03 06:10:43 -04:00
@pytest.mark.generic
2022-12-02 11:30:56 -05:00
@pytest.mark.parametrize ( ' config ' , [ ' panic_delay ' ] , indirect = True )
def test_panic_delay ( dut : PanicTestDut ) - > None :
2022-12-01 08:00:50 -05:00
dut . run_test_func ( ' test_storeprohibited ' )
2022-12-02 11:30:56 -05:00
try :
dut . expect_exact ( ' Rebooting... ' , timeout = 4 )
except pexpect . TIMEOUT :
# We are supposed to NOT find the output for the specified time
pass
else :
# If we actually match the output within the timeout, it means the delay didn't work
raise AssertionError ( ' Rebooted too early, delay is too short ' )
dut . expect_exact ( ' Rebooting... ' , timeout = 3 )
dut . expect_exact ( ' rst:0xc (SW_CPU_RESET) ' )
2023-01-06 00:16:26 -05:00
#########################
# for memprot test only #
#########################
# Memprot-related tests are supported only on targets with PMS/PMA peripheral;
2024-06-18 05:20:07 -04:00
# currently ESP32-S2, ESP32-C3, ESP32-C2, ESP32-H2, ESP32-C6, ESP32-P4 and ESP32-C5 are supported
2023-01-06 00:16:26 -05:00
CONFIGS_MEMPROT_IDRAM = [
pytest . param ( ' memprot_esp32s2 ' , marks = [ pytest . mark . esp32s2 ] ) ,
pytest . param ( ' memprot_esp32c3 ' , marks = [ pytest . mark . esp32c3 ] ) ,
2023-02-20 05:11:48 -05:00
pytest . param ( ' memprot_esp32c2 ' , marks = [ pytest . mark . esp32c2 ] ) ,
2024-06-18 05:20:07 -04:00
pytest . param ( ' memprot_esp32c5 ' , marks = [ pytest . mark . esp32c5 ] ) ,
2023-03-09 23:08:40 -05:00
pytest . param ( ' memprot_esp32c6 ' , marks = [ pytest . mark . esp32c6 ] ) ,
2024-04-11 04:11:17 -04:00
pytest . param ( ' memprot_esp32h2 ' , marks = [ pytest . mark . esp32h2 ] ) ,
pytest . param ( ' memprot_esp32p4 ' , marks = [ pytest . mark . esp32p4 ] )
2023-01-06 00:16:26 -05:00
]
CONFIGS_MEMPROT_DCACHE = [
pytest . param ( ' memprot_esp32s2 ' , marks = pytest . mark . esp32s2 ) ,
]
CONFIGS_MEMPROT_RTC_FAST_MEM = [
pytest . param ( ' memprot_esp32s2 ' , marks = [ pytest . mark . esp32s2 ] ) ,
pytest . param ( ' memprot_esp32c3 ' , marks = [ pytest . mark . esp32c3 ] ) ,
2024-06-18 05:20:07 -04:00
pytest . param ( ' memprot_esp32c5 ' , marks = [ pytest . mark . esp32c5 ] ) ,
2023-03-09 23:08:40 -05:00
pytest . param ( ' memprot_esp32c6 ' , marks = [ pytest . mark . esp32c6 ] ) ,
2024-04-11 04:11:17 -04:00
pytest . param ( ' memprot_esp32h2 ' , marks = [ pytest . mark . esp32h2 ] ) ,
pytest . param ( ' memprot_esp32p4 ' , marks = [ pytest . mark . esp32p4 ] )
2023-01-06 00:16:26 -05:00
]
CONFIGS_MEMPROT_RTC_SLOW_MEM = [
pytest . param ( ' memprot_esp32s2 ' , marks = [ pytest . mark . esp32s2 ] ) ,
]
2024-02-05 06:48:44 -05:00
CONFIGS_MEMPROT_FLASH_IDROM = [
2024-06-18 05:20:07 -04:00
pytest . param ( ' memprot_esp32c5 ' , marks = [ pytest . mark . esp32c5 ] ) ,
2024-02-05 06:48:44 -05:00
pytest . param ( ' memprot_esp32c6 ' , marks = [ pytest . mark . esp32c6 ] ) ,
2024-04-11 04:11:17 -04:00
pytest . param ( ' memprot_esp32h2 ' , marks = [ pytest . mark . esp32h2 ] ) ,
pytest . param ( ' memprot_esp32p4 ' , marks = [ pytest . mark . esp32p4 ] )
2024-02-05 06:48:44 -05:00
]
2024-05-31 12:56:59 -04:00
CONFIGS_MEMPROT_INVALID_REGION_PROTECTION_USING_PMA = [
2024-06-18 05:20:07 -04:00
pytest . param ( ' memprot_esp32c5 ' , marks = [ pytest . mark . esp32c5 ] ) ,
2024-05-31 12:56:59 -04:00
pytest . param ( ' memprot_esp32c6 ' , marks = [ pytest . mark . esp32c6 ] ) ,
pytest . param ( ' memprot_esp32h2 ' , marks = [ pytest . mark . esp32h2 ] ) ,
pytest . param ( ' memprot_esp32p4 ' , marks = [ pytest . mark . esp32p4 ] )
]
2023-01-06 00:16:26 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_DCACHE , indirect = True )
@pytest.mark.generic
def test_dcache_read_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
dut . expect_exact ( r ' Test error: Test function has returned ' )
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-06 00:16:26 -05:00
# TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_DCACHE , indirect = True )
@pytest.mark.generic
@pytest.mark.xfail ( ' config.getvalue( " target " ) == " esp32s2 " ' , reason = ' Incorrect panic reason may be observed ' , run = False )
def test_dcache_write_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
dut . expect_gme ( ' Memory protection fault ' )
dut . expect ( r ' Write operation at address [0-9xa-f]+ not permitted \ (( \ S+) \ ) ' )
dut . expect_reg_dump ( 0 )
dut . expect_backtrace ( )
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-06 00:16:26 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_IDRAM , indirect = True )
@pytest.mark.generic
def test_iram_reg1_write_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
if dut . target == ' esp32s2 ' :
dut . expect_gme ( ' Memory protection fault ' )
dut . expect ( r ' Write operation at address [0-9xa-f]+ not permitted \ (( \ S+) \ ) ' )
dut . expect_reg_dump ( 0 )
dut . expect_backtrace ( )
elif dut . target == ' esp32c3 ' :
dut . expect_exact ( r ' Test error: Test function has returned ' )
2024-06-18 05:20:07 -04:00
elif dut . target in [ ' esp32c2 ' , ' esp32c5 ' , ' esp32c6 ' , ' esp32h2 ' , ' esp32p4 ' ] :
2023-01-06 00:16:26 -05:00
dut . expect_gme ( ' Store access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-06 00:16:26 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_IDRAM , indirect = True )
@pytest.mark.generic
def test_iram_reg2_write_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
if dut . target == ' esp32s2 ' :
dut . expect_gme ( ' Memory protection fault ' )
dut . expect ( r ' Write operation at address [0-9xa-f]+ not permitted \ (( \ S+) \ ) ' )
dut . expect_reg_dump ( 0 )
dut . expect_backtrace ( )
elif dut . target == ' esp32c3 ' :
dut . expect_gme ( ' Memory protection fault ' )
dut . expect ( r ' memory type: ( \ S+) ' )
dut . expect ( r ' faulting address: [0-9xa-f]+ ' )
dut . expect ( r ' operation type: ( \ S+) ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
2024-06-18 05:20:07 -04:00
elif dut . target in [ ' esp32c2 ' , ' esp32c5 ' , ' esp32c6 ' , ' esp32h2 ' , ' esp32p4 ' ] :
2023-01-06 00:16:26 -05:00
dut . expect_gme ( ' Store access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-06 00:16:26 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_IDRAM , indirect = True )
@pytest.mark.generic
def test_iram_reg3_write_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
if dut . target == ' esp32s2 ' :
dut . expect_gme ( ' Memory protection fault ' )
dut . expect ( r ' Write operation at address [0-9xa-f]+ not permitted \ (( \ S+) \ ) ' )
dut . expect_reg_dump ( 0 )
dut . expect_backtrace ( )
elif dut . target == ' esp32c3 ' :
dut . expect_gme ( ' Memory protection fault ' )
dut . expect ( r ' memory type: ( \ S+) ' )
dut . expect ( r ' faulting address: [0-9xa-f]+ ' )
dut . expect ( r ' operation type: ( \ S+) ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
2024-06-18 05:20:07 -04:00
elif dut . target in [ ' esp32c2 ' , ' esp32c5 ' , ' esp32c6 ' , ' esp32h2 ' , ' esp32p4 ' ] :
2023-01-06 00:16:26 -05:00
dut . expect_gme ( ' Store access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-06 00:16:26 -05:00
# TODO: IDF-6820: ESP32-S2 -> Fix incorrect panic reason: Unhandled debug exception
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_IDRAM , indirect = True )
@pytest.mark.generic
@pytest.mark.xfail ( ' config.getvalue( " target " ) == " esp32s2 " ' , reason = ' Incorrect panic reason may be observed ' , run = False )
def test_iram_reg4_write_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
if dut . target == ' esp32s2 ' :
dut . expect_gme ( ' Memory protection fault ' )
dut . expect ( r ' Write operation at address [0-9xa-f]+ not permitted \ (( \ S+) \ ) ' )
dut . expect_reg_dump ( 0 )
dut . expect_backtrace ( )
elif dut . target == ' esp32c3 ' :
dut . expect_gme ( ' Memory protection fault ' )
dut . expect ( r ' memory type: ( \ S+) ' )
dut . expect ( r ' faulting address: [0-9xa-f]+ ' )
dut . expect ( r ' operation type: ( \ S+) ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
2023-03-09 23:08:40 -05:00
elif dut . target in [ ' esp32c2 ' , ' esp32c6 ' , ' eps32h2 ' ] :
2023-01-06 00:16:26 -05:00
dut . expect_gme ( ' Store access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-06 00:16:26 -05:00
# TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_IDRAM , indirect = True )
@pytest.mark.generic
@pytest.mark.xfail ( ' config.getvalue( " target " ) == " esp32s2 " ' , reason = ' Multiple panic reasons for the same test may surface ' , run = False )
def test_dram_reg1_execute_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
if dut . target == ' esp32s2 ' :
dut . expect_gme ( ' Memory protection fault ' )
dut . expect ( r ' Unknown operation at address [0-9xa-f]+ not permitted \ (( \ S+) \ ) ' )
dut . expect_reg_dump ( 0 )
dut . expect_corrupted_backtrace ( )
2024-06-18 05:20:07 -04:00
elif dut . target in [ ' esp32c3 ' , ' esp32c2 ' , ' esp32c5 ' , ' esp32c6 ' , ' esp32h2 ' , ' esp32p4 ' ] :
2023-01-06 00:16:26 -05:00
dut . expect_gme ( ' Instruction access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-06 00:16:26 -05:00
2023-04-24 21:57:23 -04:00
# TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs
2023-01-06 00:16:26 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_IDRAM , indirect = True )
@pytest.mark.generic
2023-04-24 21:57:23 -04:00
@pytest.mark.xfail ( ' config.getvalue( " target " ) == " esp32s2 " ' , reason = ' Multiple panic reasons for the same test may surface ' , run = False )
2023-01-06 00:16:26 -05:00
def test_dram_reg2_execute_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
if dut . target == ' esp32s2 ' :
dut . expect_gme ( ' InstructionFetchError ' )
dut . expect_reg_dump ( 0 )
dut . expect_corrupted_backtrace ( )
2024-06-18 05:20:07 -04:00
elif dut . target in [ ' esp32c3 ' , ' esp32c2 ' , ' esp32c5 ' , ' esp32c6 ' , ' esp32h2 ' , ' esp32p4 ' ] :
2023-01-06 00:16:26 -05:00
dut . expect_gme ( ' Instruction access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-06 00:16:26 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_RTC_FAST_MEM , indirect = True )
@pytest.mark.generic
def test_rtc_fast_reg1_execute_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
dut . expect_exact ( r ' Test error: Test function has returned ' )
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-06 00:16:26 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_RTC_FAST_MEM , indirect = True )
@pytest.mark.generic
2024-06-18 05:20:07 -04:00
@pytest.mark.skipif ( ' config.getvalue( " target " ) in [ " esp32c5 " , " esp32c6 " , " esp32h2 " , " esp32p4 " ] ' , reason = ' Not a violation condition, no PMS peripheral case ' )
2023-01-06 00:16:26 -05:00
def test_rtc_fast_reg2_execute_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
dut . expect_gme ( ' Memory protection fault ' )
if dut . target == ' esp32s2 ' :
dut . expect ( r ' Read operation at address [0-9xa-f]+ not permitted \ (( \ S+) \ ) ' )
dut . expect_reg_dump ( 0 )
dut . expect_backtrace ( )
elif dut . target == ' esp32c3 ' :
dut . expect ( r ' memory type: ( \ S+) ' )
dut . expect ( r ' faulting address: [0-9xa-f]+ ' )
dut . expect ( r ' operation type: ( \ S+) ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-06 00:16:26 -05:00
# TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_RTC_FAST_MEM , indirect = True )
@pytest.mark.generic
@pytest.mark.xfail ( ' config.getvalue( " target " ) == " esp32s2 " ' , reason = ' Multiple panic reasons for the same test may surface ' , run = False )
def test_rtc_fast_reg3_execute_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
if dut . target == ' esp32s2 ' :
2023-02-20 05:11:48 -05:00
dut . expect_gme ( ' Memory protection fault ' )
2023-01-06 00:16:26 -05:00
dut . expect ( r ' Unknown operation at address [0-9xa-f]+ not permitted \ (( \ S+) \ ) ' )
dut . expect_reg_dump ( 0 )
dut . expect_backtrace ( )
elif dut . target == ' esp32c3 ' :
2023-02-20 05:11:48 -05:00
dut . expect_gme ( ' Memory protection fault ' )
2023-01-06 00:16:26 -05:00
dut . expect ( r ' memory type: ( \ S+) ' )
dut . expect ( r ' faulting address: [0-9xa-f]+ ' )
dut . expect ( r ' operation type: ( \ S+) ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
2024-06-18 05:20:07 -04:00
elif dut . target in [ ' esp32c5 ' , ' esp32c6 ' , ' esp32h2 ' , ' esp32p4 ' ] :
2023-02-20 05:11:48 -05:00
dut . expect_gme ( ' Instruction access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
2023-01-06 00:16:26 -05:00
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-06 00:16:26 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_RTC_SLOW_MEM , indirect = True )
@pytest.mark.generic
def test_rtc_slow_reg1_execute_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
dut . expect_gme ( ' Memory protection fault ' )
dut . expect ( r ' Read operation at address [0-9xa-f]+ not permitted \ (( \ S+) \ ) ' )
dut . expect_reg_dump ( 0 )
dut . expect_corrupted_backtrace ( )
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-06 00:16:26 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_RTC_SLOW_MEM , indirect = True )
@pytest.mark.generic
def test_rtc_slow_reg2_execute_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
dut . expect_gme ( ' Memory protection fault ' )
dut . expect ( r ' Read operation at address [0-9xa-f]+ not permitted \ (( \ S+) \ ) ' )
dut . expect_reg_dump ( 0 )
dut . expect_corrupted_backtrace ( )
2023-04-25 04:28:10 -04:00
dut . expect_cpu_reset ( )
2023-01-20 00:53:29 -05:00
2024-02-05 06:48:44 -05:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_FLASH_IDROM , indirect = True )
@pytest.mark.generic
def test_irom_reg_write_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
2024-03-29 05:38:23 -04:00
dut . expect_gme ( ' Store access fault ' )
2024-02-05 06:48:44 -05:00
dut . expect_reg_dump ( 0 )
dut . expect_cpu_reset ( )
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_FLASH_IDROM , indirect = True )
@pytest.mark.generic
def test_drom_reg_write_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
dut . expect_gme ( ' Store access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_cpu_reset ( )
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_FLASH_IDROM , indirect = True )
@pytest.mark.generic
def test_drom_reg_execute_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
dut . expect_gme ( ' Instruction access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_cpu_reset ( )
2024-05-31 12:56:59 -04:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_INVALID_REGION_PROTECTION_USING_PMA , indirect = True )
@pytest.mark.generic
def test_invalid_memory_region_write_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
dut . expect_gme ( ' Store access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_cpu_reset ( )
@pytest.mark.parametrize ( ' config ' , CONFIGS_MEMPROT_INVALID_REGION_PROTECTION_USING_PMA , indirect = True )
@pytest.mark.generic
def test_invalid_memory_region_execute_violation ( dut : PanicTestDut , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
dut . expect_gme ( ' Instruction access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_cpu_reset ( )
2023-01-20 00:53:29 -05:00
@pytest.mark.esp32
2024-04-03 06:10:43 -04:00
@pytest.mark.generic
2023-01-20 00:53:29 -05:00
@pytest.mark.parametrize ( ' config ' , [ ' gdbstub_coredump ' ] , indirect = True )
def test_gdbstub_coredump ( dut : PanicTestDut ) - > None :
test_func_name = ' test_storeprohibited '
dut . run_test_func ( test_func_name )
dut . process_coredump_uart ( )
dut . expect_exact ( ' Entering gdb stub now. ' )
2024-03-11 16:19:17 -04:00
dut . start_gdb_for_gdbstub ( )
2023-01-20 00:53:29 -05:00
frames = dut . gdb_backtrace ( )
dut . verify_gdb_backtrace ( frames , get_default_backtrace ( test_func_name ) )
dut . revert_log_level ( )
return # don't expect "Rebooting" output below
2023-05-04 11:31:31 -04:00
2024-01-19 02:51:57 -05:00
def test_hw_stack_guard_cpu ( dut : PanicTestDut , cpu : int ) - > None :
dut . expect_exact ( f ' Guru Meditation Error: Core { cpu } panic \' ed (Stack protection fault). ' )
2024-03-29 05:38:23 -04:00
dut . expect_none ( ' ASSIST_DEBUG is not triggered BUT interrupt occurred! ' )
2024-01-19 02:51:57 -05:00
dut . expect_exact ( f ' Detected in task " HWSG { cpu } " ' )
addr = dut . expect ( ' at 0x([0-9a-fA-F] {8} ) ' )
assert addr . group ( 1 ) != b ' 00000000 '
addr = dut . expect ( ' Stack pointer: 0x([0-9a-fA-F] {8} ) ' )
assert addr . group ( 1 ) != b ' 00000000 '
addr = dut . expect ( r ' Stack bounds: 0x([0-9a-fA-F] {8} ) ' )
assert addr . group ( 1 ) != b ' 00000000 '
start_addr = int ( addr . group ( 1 ) , 16 )
addr = dut . expect ( r ' - 0x([0-9a-fA-F] {8} ) ' )
assert addr . group ( 1 ) != b ' 00000000 '
end_addr = int ( addr . group ( 1 ) , 16 )
assert end_addr > start_addr
2023-05-04 11:31:31 -04:00
@pytest.mark.parametrize ( ' config ' , CONFIGS_HW_STACK_GUARD , indirect = True )
@pytest.mark.generic
def test_hw_stack_guard_cpu0 ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
2024-01-19 02:51:57 -05:00
test_hw_stack_guard_cpu ( dut , 0 )
common_test ( dut , config )
@pytest.mark.parametrize ( ' config ' , CONFIGS_HW_STACK_GUARD_DUAL_CORE , indirect = True )
@pytest.mark.generic
def test_hw_stack_guard_cpu1 ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
test_hw_stack_guard_cpu ( dut , 1 )
2023-05-04 11:31:31 -04:00
common_test ( dut , config )
2023-10-11 07:24:24 -04:00
@pytest.mark.esp32
@pytest.mark.parametrize ( ' config ' , [ ' panic ' ] , indirect = True )
@pytest.mark.generic
def test_illegal_access ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
if dut . is_xtensa :
dut . expect ( r ' \ [1 \ ] val: (-? \ d+) at 0x80000000 ' , timeout = 30 )
dut . expect_gme ( ' LoadProhibited ' )
dut . expect_reg_dump ( 0 )
dut . expect_backtrace ( )
dut . expect_elf_sha256 ( )
dut . expect_none ( ' Guru Meditation ' )
2024-03-11 16:19:17 -04:00
@pytest.mark.parametrize ( ' config ' , CONFIG_CAPTURE_DRAM , indirect = True )
@pytest.mark.generic
def test_capture_dram ( dut : PanicTestDut , config : str , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
2024-05-06 09:41:25 -04:00
regex_pattern = rb ' assert failed:[ \ s \ w()]*? \ s[. \ w/]* \ .(?:c|cpp|h|hpp): \ d.*$ '
dut . expect ( re . compile ( regex_pattern , re . MULTILINE ) )
if dut . is_xtensa :
dut . expect_backtrace ( )
else :
dut . expect_stack_dump ( )
2024-03-11 16:19:17 -04:00
dut . expect_elf_sha256 ( )
dut . expect_none ( [ ' Guru Meditation ' , ' Re-entered core dump ' ] )
2024-05-06 09:41:25 -04:00
dut . expect_exact ( ' Save core dump to flash... ' )
dut . expect_exact ( ' Core dump has been saved to flash. ' )
dut . expect ( ' Rebooting... ' )
2024-03-11 16:19:17 -04:00
core_elf_file = dut . process_coredump_flash ( )
dut . start_gdb_for_coredump ( core_elf_file )
assert dut . gdb_data_eval_expr ( ' g_data_var ' ) == ' 43 '
assert dut . gdb_data_eval_expr ( ' g_bss_var ' ) == ' 55 '
assert re . search ( r ' 0x[0-9a-fA-F]+ " Coredump Test " ' , dut . gdb_data_eval_expr ( ' g_heap_ptr ' ) )
assert int ( dut . gdb_data_eval_expr ( ' g_cd_iram ' ) ) == 0x4243
assert int ( dut . gdb_data_eval_expr ( ' g_cd_dram ' ) ) == 0x4344
if dut . target != ' esp32c2 ' :
assert int ( dut . gdb_data_eval_expr ( ' g_rtc_data_var ' ) ) == 0x55AA
assert int ( dut . gdb_data_eval_expr ( ' g_rtc_fast_var ' ) ) == 0xAABBCCDD
2024-04-29 12:32:00 -04:00
def _test_coredump_summary ( dut : PanicTestDut , flash_encrypted : bool , coredump_encrypted : bool ) - > None :
dut . run_test_func ( ' test_setup_coredump_summary ' )
dut . expect_cpu_reset ( )
if flash_encrypted :
dut . expect_exact ( ' Flash encryption mode is DEVELOPMENT (not secure) ' )
dut . run_test_func ( ' test_coredump_summary ' )
if flash_encrypted and not coredump_encrypted :
dut . expect_exact ( ' Flash encryption enabled in hardware and core dump partition is not encrypted! ' )
return
dut . expect_elf_sha256 ( ' App ELF file SHA256: ' )
dut . expect_exact ( ' Crashed task: main ' )
2024-05-06 18:55:17 -04:00
if dut . is_xtensa :
2024-06-19 08:06:14 -04:00
dut . expect_exact ( ' Exception cause: 0 ' )
2024-05-06 18:55:17 -04:00
else :
2024-06-19 08:06:14 -04:00
dut . expect_exact ( ' Exception cause: 2 ' )
2024-04-29 12:32:00 -04:00
dut . expect ( PANIC_ABORT_PREFIX + r ' assert failed:[ \ s \ w()]*? \ s[. \ w/]* \ .(?:c|cpp|h|hpp): \ d.*$ ' )
@pytest.mark.generic
@pytest.mark.parametrize ( ' config ' , CONFIG_COREDUMP_SUMMARY , indirect = True )
def test_coredump_summary ( dut : PanicTestDut ) - > None :
_test_coredump_summary ( dut , False , False )
@pytest.mark.flash_encryption
@pytest.mark.parametrize ( ' config ' , CONFIG_COREDUMP_SUMMARY_FLASH_ENCRYPTED , indirect = True )
def test_coredump_summary_flash_encrypted ( dut : PanicTestDut , config : str ) - > None :
_test_coredump_summary ( dut , True , config == ' coredump_flash_encrypted ' )
2024-02-27 17:51:28 -05:00
@pytest.mark.parametrize ( ' config ' , [ pytest . param ( ' coredump_flash_elf_sha ' , marks = TARGETS_ALL ) ] , indirect = True )
@pytest.mark.generic
def test_tcb_corrupted ( dut : PanicTestDut , target : str , config : str , test_func_name : str ) - > None :
dut . run_test_func ( test_func_name )
if dut . is_xtensa :
dut . expect_gme ( ' LoadProhibited ' )
dut . expect_reg_dump ( 0 )
dut . expect_corrupted_backtrace ( )
else :
dut . expect_gme ( ' Load access fault ' )
dut . expect_reg_dump ( 0 )
dut . expect_stack_dump ( )
dut . expect_elf_sha256 ( )
dut . expect_none ( ' Guru Meditation ' )
# TCB NAME
# ---------- ----------------
if dut . is_multi_core :
regex_patterns = [ rb ' [0-9xa-fA-F] main ' ,
rb ' [0-9xa-fA-F] ipc0 ' ,
rb ' [0-9xa-fA-F] ipc1 ' ]
else :
regex_patterns = [ rb ' [0-9xa-fA-F] main ' ]
coredump_pattern = [ re . compile ( pattern . decode ( ' utf-8 ' ) ) for pattern in regex_patterns ]
common_test (
dut ,
config ,
expected_backtrace = None ,
expected_coredump = coredump_pattern
)