From 39156968c16264f553d96f3ec268f5ec6ddb64f1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 7 Sep 2026 13:59:35 +0200 Subject: [PATCH] [api] Cover repeated and sub message fields in the decode case tests --- .../api/test_api_protobuf_generator.py | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/components/api/test_api_protobuf_generator.py b/tests/unit_tests/components/api/test_api_protobuf_generator.py index 72ff18d940..76e7b453c6 100644 --- a/tests/unit_tests/components/api/test_api_protobuf_generator.py +++ b/tests/unit_tests/components/api/test_api_protobuf_generator.py @@ -45,6 +45,7 @@ def _file_with_messages( UINT64 = descriptor_pb2.FieldDescriptorProto.TYPE_UINT64 +MESSAGE = descriptor_pb2.FieldDescriptorProto.TYPE_MESSAGE INT64 = descriptor_pb2.FieldDescriptorProto.TYPE_INT64 SINT64 = descriptor_pb2.FieldDescriptorProto.TYPE_SINT64 UINT32 = descriptor_pb2.FieldDescriptorProto.TYPE_UINT32 @@ -187,9 +188,11 @@ def test_multi_byte_tag_fixed32_falls_back_to_the_generic_helper( assert content.startswith("pos = ProtoEncode::encode_"), content -def _decode_case(field_type: int, number: int) -> str: +def _decode_case(field_type: int, number: int, *, repeated: bool = False) -> str: """Return the decode_field() case the generator emits for one decoded field.""" - field = _field(field_type, number) + field = _field(field_type, number, repeated=repeated) + if field_type == MESSAGE: + field.type_name = ".Sub" return create_field_type_info( field, needs_decode=True, needs_encode=False ).decode_content @@ -216,6 +219,43 @@ def test_decode_cases_carry_field_number_and_wire_type( assert lines[-1].strip() == "break;", case +@pytest.mark.parametrize( + ("field_type", "repeated", "wire_type", "store"), + [ + (UINT32, True, "WIRE_TYPE_VARINT", "this->value.push_back(value.as_varint());"), + ( + STRING, + True, + "WIRE_TYPE_LENGTH_DELIMITED", + "this->value.push_back(value.as_string());", + ), + ( + MESSAGE, + False, + "WIRE_TYPE_LENGTH_DELIMITED", + "value.decode_to_message(this->value);", + ), + ( + MESSAGE, + True, + "WIRE_TYPE_LENGTH_DELIMITED", + "value.decode_to_message(this->value.back());", + ), + ], +) +def test_repeated_and_message_fields_decode_through_the_same_case_shape( + field_type: int, repeated: bool, wire_type: str, store: str +) -> None: + """Repeated and sub message fields land in the one switch with their own store.""" + case = _decode_case(field_type, 7, repeated=repeated) + lines = case.splitlines() + assert lines[0] == f"case proto_tag(7, {wire_type}):", case + assert store in case, case + if field_type == MESSAGE and repeated: + assert "this->value.emplace_back();" in case, case + assert lines[-1].strip() == "break;", case + + def test_message_gets_a_single_decode_field_override() -> None: """All wire types of a decoded message land in one decode_field() switch.""" desc = descriptor_pb2.DescriptorProto(name="Mixed")