mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
feat(esp_system): add linux test for system init function regisration
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
# For more information about build system see
|
||||
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
|
||||
# The following five lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
set(COMPONENTS main)
|
||||
project(test_sys_init_fn)
|
||||
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "test_sys_init_fn.c"
|
||||
"test_init_fn_defs.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES unity esp_system)
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file defines system init functions whose execution is verified
|
||||
* by the test cases in test_sys_init_fn.c.
|
||||
*
|
||||
* The functions are placed into the esp_sys_init_fn linker section via the
|
||||
* system init macro. On Linux this uses ELF section sorting; on macOS
|
||||
* the same section is resolved at runtime via getsectiondata().
|
||||
*
|
||||
* Important: this file must be compiled into the same binary as the test
|
||||
* runner so the linker/loader sees the section entries.
|
||||
*/
|
||||
|
||||
#include "esp_private/startup_internal.h"
|
||||
#include "test_init_fn_defs.h"
|
||||
|
||||
/* ---- Global state read back by the test cases ---- */
|
||||
|
||||
int trace_log[INIT_FN_TRACE_MAX];
|
||||
int trace_count = 0;
|
||||
|
||||
bool core_prio_200_executed = false;
|
||||
bool core_prio_250_executed = false;
|
||||
bool secondary_prio_200_executed = false;
|
||||
bool secondary_prio_250_executed = false;
|
||||
|
||||
/* ---- Helper ---- */
|
||||
static void trace_append(int tag)
|
||||
{
|
||||
if (trace_count < INIT_FN_TRACE_MAX) {
|
||||
trace_log[trace_count++] = tag;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- CORE-stage init functions (executed during do_core_init) ---- */
|
||||
|
||||
/*
|
||||
* Two CORE-stage functions with different priorities.
|
||||
* Priority 200 must execute before priority 250.
|
||||
* We use tag values equal to the priority for easy identification.
|
||||
*/
|
||||
ESP_SYSTEM_INIT_FN(test_core_prio_200, CORE, BIT(0), 200)
|
||||
{
|
||||
core_prio_200_executed = true;
|
||||
trace_append(200);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_SYSTEM_INIT_FN(test_core_prio_250, CORE, BIT(0), 250)
|
||||
{
|
||||
core_prio_250_executed = true;
|
||||
trace_append(250);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* ---- SECONDARY-stage init functions (executed during do_secondary_init) ---- */
|
||||
|
||||
ESP_SYSTEM_INIT_FN(test_secondary_prio_200, SECONDARY, BIT(0), 200)
|
||||
{
|
||||
secondary_prio_200_executed = true;
|
||||
trace_append(1200); /* offset by 1000 so we can distinguish stage in trace */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_SYSTEM_INIT_FN(test_secondary_prio_250, SECONDARY, BIT(0), 250)
|
||||
{
|
||||
secondary_prio_250_executed = true;
|
||||
trace_append(1250);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Maximum number of init function invocations we track for ordering tests.
|
||||
*/
|
||||
#define INIT_FN_TRACE_MAX 16
|
||||
|
||||
/**
|
||||
* Global trace log filled by init functions to record their execution order.
|
||||
* Each init function appends its own tag (an arbitrary integer) to
|
||||
* trace_log[trace_count] and increments trace_count.
|
||||
*/
|
||||
extern int trace_log[INIT_FN_TRACE_MAX];
|
||||
extern int trace_count;
|
||||
|
||||
/* Flags set by individual init functions so tests can verify they executed */
|
||||
extern bool core_prio_200_executed;
|
||||
extern bool core_prio_250_executed;
|
||||
extern bool secondary_prio_200_executed;
|
||||
extern bool secondary_prio_250_executed;
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test cases for the ESP_SYSTEM_INIT_FN mechanism.
|
||||
*
|
||||
* The init functions are defined in test_init_fn_defs.c and are executed
|
||||
* automatically during startup (before app_main). These tests inspect the
|
||||
* side-effects left by those functions to verify:
|
||||
*
|
||||
* 1. Init functions actually executed.
|
||||
* 2. CORE-stage functions executed before SECONDARY-stage functions.
|
||||
* 3. Within the same stage, lower priority values execute first.
|
||||
* 4. All expected functions ran (no silent drops).
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "unity.h"
|
||||
#include "unity_test_runner.h"
|
||||
#include "test_init_fn_defs.h"
|
||||
|
||||
/* ---------- Test cases ---------- */
|
||||
|
||||
TEST_CASE("CORE init functions executed", "[sys_init_fn]")
|
||||
{
|
||||
TEST_ASSERT_TRUE_MESSAGE(core_prio_200_executed,
|
||||
"CORE priority-200 init function did not execute");
|
||||
TEST_ASSERT_TRUE_MESSAGE(core_prio_250_executed,
|
||||
"CORE priority-250 init function did not execute");
|
||||
}
|
||||
|
||||
TEST_CASE("SECONDARY init functions executed", "[sys_init_fn]")
|
||||
{
|
||||
TEST_ASSERT_TRUE_MESSAGE(secondary_prio_200_executed,
|
||||
"SECONDARY priority-200 init function did not execute");
|
||||
TEST_ASSERT_TRUE_MESSAGE(secondary_prio_250_executed,
|
||||
"SECONDARY priority-250 init function did not execute");
|
||||
}
|
||||
|
||||
TEST_CASE("all four init functions traced", "[sys_init_fn]")
|
||||
{
|
||||
/* We registered 4 init functions total (2 CORE + 2 SECONDARY) */
|
||||
TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(4, trace_count,
|
||||
"expected at least 4 init function traces");
|
||||
}
|
||||
|
||||
TEST_CASE("CORE stage runs before SECONDARY stage", "[sys_init_fn]")
|
||||
{
|
||||
/*
|
||||
* In the trace log, CORE entries have tags < 1000,
|
||||
* SECONDARY entries have tags >= 1000.
|
||||
* All CORE entries must appear before any SECONDARY entry.
|
||||
*/
|
||||
int first_secondary = -1;
|
||||
int last_core = -1;
|
||||
|
||||
for (int i = 0; i < trace_count; i++) {
|
||||
if (trace_log[i] < 1000) {
|
||||
last_core = i;
|
||||
} else if (first_secondary < 0) {
|
||||
first_secondary = i;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(last_core >= 0, "no CORE trace entries found");
|
||||
TEST_ASSERT_TRUE_MESSAGE(first_secondary >= 0, "no SECONDARY trace entries found");
|
||||
TEST_ASSERT_LESS_THAN_INT_MESSAGE(first_secondary, last_core,
|
||||
"a CORE init function ran after a SECONDARY one");
|
||||
}
|
||||
|
||||
TEST_CASE("priority ordering within CORE stage", "[sys_init_fn]")
|
||||
{
|
||||
/*
|
||||
* Within the CORE stage, priority 200 (tag 200) must appear
|
||||
* before priority 250 (tag 250) in the trace log.
|
||||
*/
|
||||
int pos_200 = -1;
|
||||
int pos_250 = -1;
|
||||
|
||||
for (int i = 0; i < trace_count; i++) {
|
||||
if (trace_log[i] == 200 && pos_200 < 0) {
|
||||
pos_200 = i;
|
||||
}
|
||||
if (trace_log[i] == 250 && pos_250 < 0) {
|
||||
pos_250 = i;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(pos_200 >= 0, "CORE prio-200 not in trace");
|
||||
TEST_ASSERT_TRUE_MESSAGE(pos_250 >= 0, "CORE prio-250 not in trace");
|
||||
TEST_ASSERT_LESS_THAN_INT_MESSAGE(pos_250, pos_200,
|
||||
"CORE prio-200 did not run before prio-250");
|
||||
}
|
||||
|
||||
TEST_CASE("priority ordering within SECONDARY stage", "[sys_init_fn]")
|
||||
{
|
||||
int pos_1200 = -1;
|
||||
int pos_1250 = -1;
|
||||
|
||||
for (int i = 0; i < trace_count; i++) {
|
||||
if (trace_log[i] == 1200 && pos_1200 < 0) {
|
||||
pos_1200 = i;
|
||||
}
|
||||
if (trace_log[i] == 1250 && pos_1250 < 0) {
|
||||
pos_1250 = i;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(pos_1200 >= 0, "SECONDARY prio-200 not in trace");
|
||||
TEST_ASSERT_TRUE_MESSAGE(pos_1250 >= 0, "SECONDARY prio-250 not in trace");
|
||||
TEST_ASSERT_LESS_THAN_INT_MESSAGE(pos_1250, pos_1200,
|
||||
"SECONDARY prio-200 did not run before prio-250");
|
||||
}
|
||||
|
||||
/* ---------- Entry point ---------- */
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
printf("Running sys_init_fn host test app\n");
|
||||
unity_run_menu();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded_idf.dut import IdfDut
|
||||
from pytest_embedded_idf.utils import idf_parametrize
|
||||
|
||||
|
||||
@pytest.mark.host_test
|
||||
@idf_parametrize('target', ['linux'], indirect=['target'])
|
||||
def test_sys_init_fn_linux(dut: IdfDut) -> None:
|
||||
dut.run_all_single_board_cases(timeout=60)
|
||||
|
||||
|
||||
@pytest.mark.host_test
|
||||
@pytest.mark.macos
|
||||
@idf_parametrize('target', ['linux'], indirect=['target'])
|
||||
def test_sys_init_fn_macos(dut: IdfDut) -> None:
|
||||
dut.run_all_single_board_cases(timeout=60)
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
Reference in New Issue
Block a user