1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-12 23:03:46 +01:00

uart grouping

This commit is contained in:
J. Nick Koston
2025-10-08 18:05:49 -10:00
parent 361c8dba36
commit 11298ca485
4 changed files with 18 additions and 126 deletions

View File

@@ -347,7 +347,7 @@ def final_validate_device_schema(
def validate_pin(opt, device): def validate_pin(opt, device):
def validator(value): def validator(value):
if opt in device: if opt in device and not CORE.testing_mode:
raise cv.Invalid( raise cv.Invalid(
f"The uart {opt} is used both by {name} and {device[opt]}, " f"The uart {opt} is used both by {name} and {device[opt]}, "
f"but can only be used by one. Please create a new uart bus for {name}." f"but can only be used by one. Please create a new uart bus for {name}."

View File

@@ -50,16 +50,26 @@ VALID_BUS_CONFIGS = {
"uart_9600_even", "uart_9600_even",
} }
# Bus types that support component grouping # Bus types that support component grouping for config validation
# I2C and SPI are shared buses with addressing/CS pins # I2C and SPI are shared buses with addressing/CS pins
# BLE sensors scan independently and don't conflict # BLE sensors scan independently and don't conflict
# UART is point-to-point and components would conflict on the same bus # UART is point-to-point but can be grouped for testing since --testing-mode
# bypasses the conflict validation (we only care that configs compile)
GROUPABLE_BUS_TYPES = { GROUPABLE_BUS_TYPES = {
"ble", "ble",
"i2c", "i2c",
"i2c_low_freq", "i2c_low_freq",
"qspi", "qspi",
"spi", "spi",
"uart",
"uart_115200",
"uart_1200",
"uart_1200_even",
"uart_19200",
"uart_38400",
"uart_4800",
"uart_4800_even",
"uart_9600_even",
} }
@@ -194,15 +204,15 @@ def create_grouping_signature(
"""Create a signature string for grouping components. """Create a signature string for grouping components.
Components with the same signature can be grouped together for testing. Components with the same signature can be grouped together for testing.
Only includes groupable bus types (I2C, SPI, BLE) - excludes point-to-point Includes groupable bus types (I2C, SPI, BLE, UART) that can be validated
protocols like UART that can't be shared. together using --testing-mode to bypass runtime conflicts.
Args: Args:
platform_buses: Mapping of platform to list of buses platform_buses: Mapping of platform to list of buses
platform: The specific platform to create signature for platform: The specific platform to create signature for
Returns: Returns:
Signature string (e.g., "i2c" or "spi") or empty if no groupable buses Signature string (e.g., "i2c" or "uart") or empty if no groupable buses
""" """
buses = platform_buses.get(platform, []) buses = platform_buses.get(platform, [])
if not buses: if not buses:

View File

@@ -1,119 +0,0 @@
#!/usr/bin/env bash
set -e
help() {
echo "Usage: $0 [-e <config|compile|clean>] [-c <string>] [-t <string>] [-f]" 1>&2
echo 1>&2
echo " - e - Parameter for esphome command. Default compile. Common alternative is config." 1>&2
echo " - c - Component folder name(s) to test. Default *. Supports comma-separated list. E.g. '-c logger' or '-c logger,api,ota'." 1>&2
echo " - t - Target name to test. Put '-t list' to display all possibilities. E.g. '-t esp32-s2-idf-51'." 1>&2
echo " - f - Continue on fail. Don't exit on first error." 1>&2
exit 1
}
# Parse parameter:
# - `e` - Parameter for `esphome` command. Default `compile`. Common alternative is `config`.
# - `c` - Component folder name to test. Default `*`.
# - `f` - Continue on fail flag.
esphome_command="compile"
target_component="*"
continue_on_fail=false
while getopts e:c:t:f flag
do
case $flag in
e) esphome_command=${OPTARG};;
c) target_component=${OPTARG};;
t) requested_target_platform=${OPTARG};;
f) continue_on_fail=true;;
\?) help;;
esac
done
cd "$(dirname "$0")/.."
if ! [ -d "./tests/test_build_components/build" ]; then
mkdir ./tests/test_build_components/build
fi
start_esphome() {
if [ -n "$requested_target_platform" ] && [ "$requested_target_platform" != "$target_platform_with_version" ]; then
echo "Skipping $target_platform_with_version"
return
fi
# create dynamic yaml file in `build` folder.
# `./tests/test_build_components/build/[target_component].[test_name].[target_platform_with_version].yaml`
component_test_file="./tests/test_build_components/build/$target_component.$test_name.$target_platform_with_version.yaml"
cp $target_platform_file $component_test_file
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS sed is...different
sed -i '' "s!\$component_test_file!../../.$f!g" $component_test_file
else
sed -i "s!\$component_test_file!../../.$f!g" $component_test_file
fi
# Start esphome process
echo "> [$target_component] [$test_name] [$target_platform_with_version]"
set -x
# TODO: Validate escape of Command line substitution value
if [ "$continue_on_fail" = true ]; then
python3 -m esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file || true
else
python3 -m esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file
fi
{ set +x; } 2>/dev/null
}
# Split comma-separated components into array
IFS=',' read -r -a component_list <<< "$target_component"
# Find all test yaml files.
# - `./tests/components/[target_component]/[test_name].[target_platform].yaml`
# - `./tests/components/[target_component]/[test_name].all.yaml`
for component_pattern in "${component_list[@]}"; do
for f in ./tests/components/$component_pattern/*.*.yaml; do
[ -f "$f" ] || continue
IFS='/' read -r -a folder_name <<< "$f"
target_component="${folder_name[3]}"
IFS='.' read -r -a file_name <<< "${folder_name[4]}"
test_name="${file_name[0]}"
target_platform="${file_name[1]}"
file_name_parts=${#file_name[@]}
if [ "$target_platform" = "all" ] || [ $file_name_parts = 2 ]; then
# Test has *not* defined a specific target platform. Need to run tests for all possible target platforms.
for target_platform_file in ./tests/test_build_components/build_components_base.*.yaml; do
IFS='/' read -r -a folder_name <<< "$target_platform_file"
IFS='.' read -r -a file_name <<< "${folder_name[3]}"
target_platform="${file_name[1]}"
start_esphome
done
else
# Test has defined a specific target platform.
# Validate we have a base test yaml for selected platform.
# The target_platform is sourced from the following location.
# 1. `./tests/test_build_components/build_components_base.[target_platform].yaml`
# 2. `./tests/test_build_components/build_components_base.[target_platform]-ard.yaml`
target_platform_file="./tests/test_build_components/build_components_base.$target_platform.yaml"
if ! [ -f "$target_platform_file" ]; then
echo "No base test file [./tests/test_build_components/build_components_base.$target_platform.yaml] for component test [$f] found."
exit 1
fi
for target_platform_file in ./tests/test_build_components/build_components_base.$target_platform*.yaml; do
# trim off "./tests/test_build_components/build_components_base." prefix
target_platform_with_version=${target_platform_file:52}
# ...now remove suffix starting with "." leaving just the test target hardware and software platform (possibly with version)
# For example: "esp32-s3-idf-50"
target_platform_with_version=${target_platform_with_version%.*}
start_esphome
done
fi
done
done

View File

@@ -0,0 +1 @@
test_build_components.py

View File

@@ -336,7 +336,7 @@ def run_grouped_component_tests(
if buses: if buses:
signature = create_grouping_signature({platform: buses}, platform) signature = create_grouping_signature({platform: buses}, platform)
# Only add to grouped_components if signature is non-empty # Only add to grouped_components if signature is non-empty
# (empty means only non-groupable buses like UART) # (empty means component has no groupable bus configurations)
if signature: if signature:
grouped_components[(platform, signature)].append(component) grouped_components[(platform, signature)].append(component)