mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
feat(esp_system): add linux test for system init function regisration
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This file is used to check the order of execution of ESP_SYSTEM_INIT_FN functions.
|
||||
@@ -13,12 +13,14 @@ import itertools
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import typing
|
||||
|
||||
ESP_SYSTEM_INIT_FN_STR = r'ESP_SYSTEM_INIT_FN'
|
||||
ESP_SYSTEM_INIT_FN_REGEX_SIMPLE = re.compile(r'ESP_SYSTEM_INIT_FN')
|
||||
ESP_SYSTEM_INIT_FN_REGEX = re.compile(r'ESP_SYSTEM_INIT_FN\(([a-zA-Z0-9_]+)\s*,\s*([a-zA-Z\ _0-9\(\)|]+)\s*,\s*([a-zA-Z\ _0-9\(\)|]+)\s*,\s*([0-9]+)\)')
|
||||
COMMENT_REGEX = re.compile(r'//.*?$|/\*.*?\*/', re.DOTALL | re.MULTILINE)
|
||||
ESP_SYSTEM_INIT_FN_REGEX_SIMPLE = re.compile(r'\bESP_SYSTEM_INIT_FN\s*\(')
|
||||
ESP_SYSTEM_INIT_FN_REGEX = re.compile(
|
||||
r'ESP_SYSTEM_INIT_FN\(([a-zA-Z0-9_]+)\s*,\s*([a-zA-Z\ _0-9\(\)|]+)\s*,\s*([a-zA-Z\ _0-9\(\)|]+)\s*,\s*([0-9]+)\)'
|
||||
)
|
||||
STARTUP_ENTRIES_FILE = 'components/esp_system/system_init_fn.txt'
|
||||
EXCLUDED_SOURCE_DIRS = {'test_apps', 'host_test', 'host_tests'}
|
||||
|
||||
|
||||
class StartupEntry:
|
||||
@@ -33,6 +35,15 @@ class StartupEntry:
|
||||
return f'{self.stage}: {self.priority:3d}: {self.func} in {self.filename} on {self.affinity}'
|
||||
|
||||
|
||||
def should_skip_source_file(filename: str, idf_path: str) -> bool:
|
||||
relpath_parts = os.path.relpath(filename, idf_path).split(os.sep)
|
||||
return any(part in EXCLUDED_SOURCE_DIRS for part in relpath_parts)
|
||||
|
||||
|
||||
def strip_comments(contents: str) -> str:
|
||||
return COMMENT_REGEX.sub('', contents)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
try:
|
||||
idf_path = os.environ['IDF_PATH']
|
||||
@@ -40,7 +51,7 @@ def main() -> None:
|
||||
raise SystemExit('IDF_PATH must be set before running this script')
|
||||
|
||||
has_errors = False
|
||||
startup_entries = [] # type: typing.List[StartupEntry]
|
||||
startup_entries: list[StartupEntry] = []
|
||||
|
||||
#
|
||||
# 1. Iterate over all .c and .cpp source files and find ESP_SYSTEM_INIT_FN definitions
|
||||
@@ -50,24 +61,32 @@ def main() -> None:
|
||||
glob_iter = glob.glob(os.path.join(idf_path, 'components', '**', f'*.{extension}'), recursive=True)
|
||||
source_files_iters.append(glob_iter)
|
||||
for filename in itertools.chain(*source_files_iters):
|
||||
with open(filename, 'r', encoding='utf-8') as f_obj:
|
||||
file_contents = f_obj.read()
|
||||
if ESP_SYSTEM_INIT_FN_STR not in file_contents:
|
||||
if should_skip_source_file(filename, idf_path):
|
||||
continue
|
||||
count_expected = len(ESP_SYSTEM_INIT_FN_REGEX_SIMPLE.findall(file_contents))
|
||||
found = ESP_SYSTEM_INIT_FN_REGEX.findall(file_contents)
|
||||
|
||||
relpath = os.path.relpath(filename, idf_path)
|
||||
with open(filename, encoding='utf-8') as f_obj:
|
||||
file_contents = f_obj.read()
|
||||
|
||||
file_contents_no_comments = strip_comments(file_contents)
|
||||
if not ESP_SYSTEM_INIT_FN_REGEX_SIMPLE.search(file_contents_no_comments):
|
||||
continue
|
||||
|
||||
count_expected = len(ESP_SYSTEM_INIT_FN_REGEX_SIMPLE.findall(file_contents_no_comments))
|
||||
found = ESP_SYSTEM_INIT_FN_REGEX.findall(file_contents_no_comments)
|
||||
if len(found) != count_expected:
|
||||
print((f'error: In {filename}, found ESP_SYSTEM_INIT_FN {count_expected} time(s), '
|
||||
f'but regular expression matched {len(found)} time(s)'), file=sys.stderr)
|
||||
print(
|
||||
(
|
||||
f'error: In {filename}, found ESP_SYSTEM_INIT_FN {count_expected} time(s), '
|
||||
f'but regular expression matched {len(found)} time(s)'
|
||||
),
|
||||
file=sys.stderr,
|
||||
)
|
||||
has_errors = True
|
||||
|
||||
for match in found:
|
||||
entry = StartupEntry(
|
||||
filename=os.path.relpath(filename, idf_path),
|
||||
func=match[0],
|
||||
stage=match[1],
|
||||
affinity=match[2],
|
||||
priority=int(match[3])
|
||||
filename=relpath, func=match[0], stage=match[1], affinity=match[2], priority=int(match[3])
|
||||
)
|
||||
startup_entries.append(entry)
|
||||
|
||||
@@ -77,7 +96,7 @@ def main() -> None:
|
||||
# to have a stable sorting order in case when the same startup function is defined in multiple files,
|
||||
# for example for different targets.
|
||||
#
|
||||
def sort_key(entry: StartupEntry) -> typing.Tuple[str, int, str]:
|
||||
def sort_key(entry: StartupEntry) -> tuple[str, int, str]:
|
||||
# luckily 'core' and 'secondary' are in alphabetical order, so we can return the string
|
||||
return (entry.stage, entry.priority, entry.filename)
|
||||
|
||||
@@ -88,7 +107,7 @@ def main() -> None:
|
||||
# 3. Load startup entries list from STARTUP_ENTRIES_FILE, removing comments and empty lines
|
||||
#
|
||||
startup_entries_expected_lines = []
|
||||
with open(os.path.join(idf_path, STARTUP_ENTRIES_FILE), 'r', encoding='utf-8') as startup_entries_expected_file:
|
||||
with open(os.path.join(idf_path, STARTUP_ENTRIES_FILE), encoding='utf-8') as startup_entries_expected_file:
|
||||
for line in startup_entries_expected_file:
|
||||
if line.startswith('#') or len(line.strip()) == 0:
|
||||
continue
|
||||
@@ -99,8 +118,13 @@ def main() -> None:
|
||||
#
|
||||
diff_lines = list(difflib.unified_diff(startup_entries_expected_lines, startup_entries_lines, lineterm=''))
|
||||
if len(diff_lines) > 0:
|
||||
print(('error: startup order doesn\'t match the reference file. '
|
||||
f'please update {STARTUP_ENTRIES_FILE} to match the actual startup order:'), file=sys.stderr)
|
||||
print(
|
||||
(
|
||||
"error: startup order doesn't match the reference file. "
|
||||
f'please update {STARTUP_ENTRIES_FILE} to match the actual startup order:'
|
||||
),
|
||||
file=sys.stderr,
|
||||
)
|
||||
for line in diff_lines:
|
||||
print(f'{line}', file=sys.stderr)
|
||||
has_errors = True
|
||||
|
||||
Reference in New Issue
Block a user