Merge branch 'dev' into decouple_scheduler_loop_cadence

This commit is contained in:
J. Nick Koston
2026-04-21 04:55:41 +02:00
committed by GitHub
47 changed files with 1096 additions and 672 deletions
@@ -0,0 +1,20 @@
esphome:
name: test
esp32:
board: esp32dev
framework:
type: arduino
spi:
clk_pin: GPIO18
mosi_pin: GPIO23
display:
- platform: ili9xxx
id: tft_display
model: ST7789V
cs_pin: GPIO5
dc_pin: GPIO17
reset_pin: GPIO16
invert_colors: false
@@ -0,0 +1,31 @@
"""Tests for the ili9xxx component."""
from __future__ import annotations
from collections.abc import Callable
from pathlib import Path
def test_ili9xxx_placement_new_uses_model_subclass(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
"""Regression test for ili9xxx picking the right constructor under placement new.
ili9xxx declares the ID as the base ``ILI9XXXDisplay`` but constructs a
model-specific subclass (e.g. ``ILI9XXXST7789V``) via ``MODELS[...].new()``.
Pvariable must emit placement new for the subclass — otherwise the base
default constructor runs and the panel is left with a null init sequence
and 0x0 dimensions, producing a silent blank screen.
"""
main_cpp = generate_main(component_config_path("ili9xxx_test.yaml"))
# Storage is sized for the subclass so the full object fits.
assert "sizeof(ili9xxx::ILI9XXXST7789V)" in main_cpp
assert "alignas(ili9xxx::ILI9XXXST7789V)" in main_cpp
# Pointer is declared as the base type for polymorphism.
assert "static ili9xxx::ILI9XXXDisplay *const tft_display" in main_cpp
# Placement new runs the subclass constructor — this is the actual regression fix.
assert "new(tft_display) ili9xxx::ILI9XXXST7789V()" in main_cpp
# Base-class default constructor must NOT be used.
assert "new(tft_display) ili9xxx::ILI9XXXDisplay()" not in main_cpp
@@ -7,6 +7,11 @@ import pytest
from esphome import config_validation as cv
from esphome.components.esp32 import KEY_BOARD, VARIANT_ESP32P4
# Importing xl9535 registers its pin schema with pins.PIN_SCHEMA_REGISTRY so that
# models (e.g. SEEED-RETERMINAL-D1001) that reference xl9535-backed pins in their
# defaults can be validated by the mipi_dsi CONFIG_SCHEMA in this test.
import esphome.components.xl9535 # noqa: F401
from esphome.const import (
CONF_DIMENSIONS,
CONF_HEIGHT,
@@ -145,3 +145,19 @@ display:
it.filled_rectangle(0, 0, it.get_width(), it.get_height(), Color::WHITE);
it.circle(it.get_width() / 2, it.get_height() / 2, 30, Color::BLACK);
it.circle(it.get_width() / 2, it.get_height() / 2, 20, Color(255, 0, 0));
- platform: epaper_spi
spi_id: spi_bus
model: goodisplay-gdey042t81-4.2
cs_pin:
allow_other_uses: true
number: GPIO5
dc_pin:
allow_other_uses: true
number: GPIO17
reset_pin:
allow_other_uses: true
number: GPIO16
busy_pin:
allow_other_uses: true
number: GPIO4
@@ -0,0 +1,22 @@
#include <gtest/gtest.h>
#include "esphome/components/modbus/modbus_helpers.h"
namespace esphome::modbus::helpers {
TEST(ModbusHelpersTest, PayloadToNumberRejectsOffsetAtEndOfBuffer) {
const std::vector<uint8_t> data{0x12, 0x34};
EXPECT_EQ(payload_to_number(data, SensorValueType::U_WORD, 2, 0xFFFFFFFF), 0);
}
TEST(ModbusHelpersTest, PayloadToNumberRejectsTruncatedMultiRegisterValue) {
const std::vector<uint8_t> data{0x12, 0x34, 0x56};
EXPECT_EQ(payload_to_number(data, SensorValueType::U_DWORD, 0, 0xFFFFFFFF), 0);
}
TEST(ModbusHelpersTest, PayloadToNumberDecodesValidWord) {
const std::vector<uint8_t> data{0x12, 0x34};
EXPECT_EQ(payload_to_number(data, SensorValueType::U_WORD, 0, 0xFFFFFFFF), 0x1234);
}
} // namespace esphome::modbus::helpers
+16
View File
@@ -3,6 +3,22 @@ esphome:
then:
- rtttl.play: 'siren:d=8,o=5,b=100:d,e,d,e,d,e,d,e'
- rtttl.stop
# Test all note features: all notes, denominators (1,2,4,8,16,32), sharp (#), octaves (4-7), dotted (.), note gap (c5,c5), pause (p)
- rtttl.play: 'special:d=4,o=5,b=120:1c4,2d#5,4e6.,8f#7,16g4,32a5,8a#5,4b6,8h5,c5,c5,8p,2c4'
# Different orders of control parameters
- rtttl.play: 'test_odb:o=5,d=8,b=100:c'
- rtttl.play: 'test_bod:b=100,o=5,d=8:c'
- rtttl.play: 'test_bdo:b=100,d=8,o=5:c'
- rtttl.play: 'test_obd:o=5,b=100,d=8:c'
- rtttl.play: 'test_dbo:d=8,b=100,o=5:c'
# Missing parameters (use defaults)
- rtttl.play: 'test_no_d:o=5,b=100:c'
- rtttl.play: 'test_no_o:d=8,b=100:c'
- rtttl.play: 'test_no_b:d=8,o=5:c'
- rtttl.play: 'test_only_d:d=8:c'
- rtttl.play: 'test_only_o:o=5:c'
- rtttl.play: 'test_only_b:b=100:c'
- rtttl.play: 'test_empty::c'
output:
- platform: ${output_platform}