test: check_init_priorities: add a test for initlevels

Add a test for check_init_priorities --initlevels in addition to the
normal error output, this validates that the function names are printed
correctly.

The current case covers sys_init, device with no init functions and
device with init function so it should be all cases.

Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
This commit is contained in:
Fabio Baltieri 2025-07-23 19:31:05 +01:00 committed by Chris Friedt
parent b1fccaad6e
commit d710ba4d04
3 changed files with 62 additions and 27 deletions

View File

@ -4,10 +4,11 @@ cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
set(output_file ${PROJECT_BINARY_DIR}/check_init_priorities_output.txt)
set(output_file_initlevels ${PROJECT_BINARY_DIR}/check_init_priorities_output_initlevels.txt)
add_custom_command(
COMMENT "Running check_init_priorities.py"
OUTPUT ${output_file}
OUTPUT ${output_file} ${output_file_initlevels}
DEPENDS
${logical_target_for_zephyr_elf}
$<$<TARGET_EXISTS:native_runner_executable>:native_runner_executable>
@ -16,11 +17,16 @@ add_custom_command(
--verbose
--output ${output_file}
--always-succeed
COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/check_init_priorities.py
--elf-file=$<IF:$<TARGET_EXISTS:native_runner_executable>,${BYPRODUCT_KERNEL_EXE_NAME},${BYPRODUCT_KERNEL_ELF_NAME}>
--initlevels
--always-succeed
> ${output_file_initlevels}
COMMAND ${PYTHON_EXECUTABLE} ${APPLICATION_SOURCE_DIR}/validate_check_init_priorities_output.py
${output_file}
${output_file} ${output_file_initlevels}
)
add_custom_target(check_init_priorities_output ALL DEPENDS ${output_file})
add_custom_target(check_init_priorities_output ALL DEPENDS ${output_file} ${output_file_initlevels})
project(check_init_priorities)

View File

@ -6,9 +6,19 @@
#include <zephyr/device.h>
DEVICE_DT_DEFINE(DT_INST(0, vnd_gpio_device), NULL, NULL, NULL, NULL,
static int init_fn_0(const struct device *dev)
{
return 0;
}
static int init_fn_1(const struct device *dev)
{
return 0;
}
DEVICE_DT_DEFINE(DT_INST(0, vnd_gpio_device), init_fn_0, NULL, NULL, NULL,
PRE_KERNEL_1, 50, NULL);
DEVICE_DT_DEFINE(DT_INST(0, vnd_i2c), NULL, NULL, NULL, NULL,
DEVICE_DT_DEFINE(DT_INST(0, vnd_i2c), init_fn_1, NULL, NULL, NULL,
PRE_KERNEL_1, 50, NULL);
DEVICE_DT_DEFINE(DT_INST(0, vnd_i2c_device), NULL, NULL, NULL, NULL,

View File

@ -9,33 +9,52 @@ import sys
REFERENCE_OUTPUT = [
"ERROR: Device initialization priority validation failed, the sequence of initialization calls does not match the devicetree dependencies.",
"ERROR: /i2c@11112222/test-i2c-dev@10 <NULL> is initialized before its dependency /gpio@ffff <NULL> (PRE_KERNEL_1+0 < PRE_KERNEL_1+1)",
"ERROR: /i2c@11112222/test-i2c-dev@10 <NULL> is initialized before its dependency /i2c@11112222 <NULL> (PRE_KERNEL_1+0 < PRE_KERNEL_1+2)",
"INFO: /i2c@11112222/test-i2c-dev@11 <NULL> PRE_KERNEL_1+3 > /gpio@ffff <NULL> PRE_KERNEL_1+1",
"INFO: /i2c@11112222/test-i2c-dev@11 <NULL> PRE_KERNEL_1+3 > /i2c@11112222 <NULL> PRE_KERNEL_1+2",
"ERROR: /i2c@11112222/test-i2c-dev@10 <NULL> is initialized before its dependency /gpio@ffff <init_fn_0> (PRE_KERNEL_1+0 < PRE_KERNEL_1+1)",
"ERROR: /i2c@11112222/test-i2c-dev@10 <NULL> is initialized before its dependency /i2c@11112222 <init_fn_1> (PRE_KERNEL_1+0 < PRE_KERNEL_1+2)",
"INFO: /i2c@11112222/test-i2c-dev@11 <NULL> PRE_KERNEL_1+3 > /gpio@ffff <init_fn_0> PRE_KERNEL_1+1",
"INFO: /i2c@11112222/test-i2c-dev@11 <NULL> PRE_KERNEL_1+3 > /i2c@11112222 <init_fn_1> PRE_KERNEL_1+2",
]
if len(sys.argv) != 2:
print(f"usage: {sys.argv[0]} FILE_PATH")
REFERENCE_OUTPUT_INITLEVELS = [
"EARLY",
"PRE_KERNEL_1",
"__init___device_dts_ord_32: init_fn_0(__device_dts_ord_32)",
"__init___device_dts_ord_33: init_fn_1(__device_dts_ord_33)",
"__init___device_dts_ord_34: NULL(__device_dts_ord_34)",
"__init___device_dts_ord_35: NULL(__device_dts_ord_35)",
"__init_posix_arch_console_init: posix_arch_console_init(NULL)",
"PRE_KERNEL_2",
"__init_sys_clock_driver_init: sys_clock_driver_init(NULL)",
"POST_KERNEL",
"APPLICATION",
"SMP",
]
if len(sys.argv) != 3:
print(f"usage: {sys.argv[0]} FILE_PATH FILE_PATH_INITLEVELS")
sys.exit(1)
output = []
with open(sys.argv[1], "r") as file:
for line in file:
if line.startswith("INFO: check_init_priorities"):
continue
output.append(line.strip())
def check_file(file_name, expect):
output = []
with open(file_name, "r") as file:
for line in file:
if line.startswith("INFO: check_init_priorities"):
continue
output.append(line.strip())
if sorted(REFERENCE_OUTPUT) != sorted(output):
print("Mismatched otuput")
print()
print("expected:")
print("\n".join(sorted(REFERENCE_OUTPUT)))
print()
print("got:")
print("\n".join(sorted(output)))
print("TEST FAILED")
sys.exit(1)
if sorted(expect) != sorted(output):
print(f"Mismatched otuput from {file_name}")
print()
print("expected:")
print("\n".join(sorted(expect)))
print()
print("got:")
print("\n".join(sorted(output)))
print("TEST FAILED")
sys.exit(1)
check_file(sys.argv[1], REFERENCE_OUTPUT)
check_file(sys.argv[2], REFERENCE_OUTPUT_INITLEVELS)
print("TEST PASSED")
sys.exit(0)