[api] Default response only string fields to a null StringRef (#19025)

This commit is contained in:
J. Nick Koston
2026-09-24 15:52:37 +01:00
committed by GitHub
parent 6f71b9102b
commit 9f5ac44db1
6 changed files with 240 additions and 59 deletions
@@ -18,7 +18,9 @@ sys.path.insert(0, str(Path(__file__).parents[4] / "script" / "api_protobuf"))
import aioesphomeapi.api_options_pb2 as pb # noqa: E402
from api_protobuf import ( # noqa: E402
MAX_MESSAGE_ID,
SOURCE_BOTH,
SOURCE_CLIENT,
SOURCE_SERVER,
_make_ifdef_line,
build_message_type,
create_field_type_info,
@@ -199,6 +201,24 @@ def _decode_case(field_type: int, number: int, *, repeated: bool = False) -> str
).decode_content
@pytest.mark.parametrize(
("needs_decode", "force", "member"),
[
(False, False, "StringRef value{nullptr, 0}; // null until set, encode only"),
(True, False, "StringRef value{};"),
(False, True, "StringRef value{};"),
],
)
def test_string_fields_default_to_null_only_when_never_read(
needs_decode: bool, force: bool, member: str
) -> None:
"""Only a string that is neither decoded nor force encoded may start as a null StringRef."""
ti = create_field_type_info(
_field(STRING, force=force), needs_decode=needs_decode, needs_encode=True
)
assert ti.public_content == [member]
@pytest.mark.parametrize(
("field_type", "number", "wire_type", "accessor"),
[
@@ -290,3 +310,21 @@ def test_message_gets_a_single_decode_field_override() -> None:
(3, "WIRE_TYPE_FIXED32"),
):
assert f"case proto_tag({number}, {wire_type}):" in cpp, cpp
@pytest.mark.parametrize("source", [SOURCE_CLIENT, SOURCE_SERVER, SOURCE_BOTH])
def test_repeated_strings_generate_in_every_direction(source: int) -> None:
"""A repeated string builds its element type from the type map, so the null
default plumbing on the pointer string type never sees it."""
desc = descriptor_pb2.DescriptorProto(name="Names")
desc.field.add(
name="names",
number=1,
type=STRING,
label=descriptor_pb2.FieldDescriptorProto.LABEL_REPEATED,
)
header, cpp, _ = build_message_type(desc, {}, {"Names": source})
assert "std::vector<std::string> names{};" in header
assert "nullptr" not in header
if source != SOURCE_SERVER:
assert "case proto_tag(1, WIRE_TYPE_LENGTH_DELIMITED):" in cpp