diff --git a/ni_measurementlink_service/_internal/parameter/serializer.py b/ni_measurementlink_service/_internal/parameter/serializer.py index e43ab57c1..67d24ef84 100644 --- a/ni_measurementlink_service/_internal/parameter/serializer.py +++ b/ni_measurementlink_service/_internal/parameter/serializer.py @@ -5,7 +5,9 @@ from typing import Any, Dict, Sequence, cast from google.protobuf.descriptor import FieldDescriptor -from google.protobuf.internal import encoder +from google.protobuf.internal.decoder import ( # type: ignore[attr-defined] + _DecodeSignedVarint32, +) from google.protobuf.message import Message from ni_measurementlink_service._internal.parameter import serialization_strategy @@ -101,22 +103,6 @@ def serialize_default_values(parameter_metadata_dict: Dict[int, ParameterMetadat return serialize_parameters(parameter_metadata_dict, default_value_parameter_array) -def _get_field_index(parameter_bytes: bytes, tag_position: int) -> int: - """Get the Filed Index based on the tag's position. - - The tag Position should be the index of the TagValue in the ByteArray for valid field index. - - Args: - parameter_bytes (bytes): Serialized bytes - - tag_position (int): Tag position - - Returns: - int: Filed index of the Tag Position - """ - return parameter_bytes[tag_position] >> _GRPC_WIRE_TYPE_BIT_WIDTH - - def _get_overlapping_parameters( parameter_metadata_dict: Dict[int, ParameterMetadata], parameter_bytes: bytes ) -> Dict[int, Any]: @@ -136,8 +122,10 @@ def _get_overlapping_parameters( # inner_decoder update the overlapping_parameters overlapping_parameters_by_id: Dict[int, Any] = {} position = 0 + parameter_bytes_memory_view = memoryview(parameter_bytes) while position < len(parameter_bytes): - field_index = _get_field_index(parameter_bytes, position) + (tag, position) = _DecodeSignedVarint32(parameter_bytes_memory_view, position) + field_index = tag >> _GRPC_WIRE_TYPE_BIT_WIDTH if field_index not in parameter_metadata_dict: raise Exception( f"Error occurred while reading the parameter - given protobuf index '{field_index}' is invalid." @@ -147,11 +135,9 @@ def _get_overlapping_parameters( field_metadata.type, field_metadata.repeated, field_metadata.message_type ) inner_decoder = decoder(field_index, cast(FieldDescriptor, field_index)) - parameter_bytes_io = BytesIO(parameter_bytes) - parameter_bytes_memory_view = parameter_bytes_io.getbuffer() position = inner_decoder( parameter_bytes_memory_view, - position + encoder._TagSize(field_index), # type: ignore[attr-defined] + position, len(parameter_bytes), cast(Message, None), # unused - See serialization_strategy._vector_decoder._new_default cast(Dict[FieldDescriptor, Any], overlapping_parameters_by_id), diff --git a/tests/assets/bigmessage.proto b/tests/assets/bigmessage.proto new file mode 100644 index 000000000..eebc1c6b6 --- /dev/null +++ b/tests/assets/bigmessage.proto @@ -0,0 +1,105 @@ +syntax = "proto3"; +package ni.measurementlink.measurement.tests.v1; + +message BigMessage { + double field1 = 1; + double field2 = 2; + double field3 = 3; + double field4 = 4; + double field5 = 5; + double field6 = 6; + double field7 = 7; + double field8 = 8; + double field9 = 9; + double field10 = 10; + double field11 = 11; + double field12 = 12; + double field13 = 13; + double field14 = 14; + double field15 = 15; + double field16 = 16; + double field17 = 17; + double field18 = 18; + double field19 = 19; + double field20 = 20; + double field21 = 21; + double field22 = 22; + double field23 = 23; + double field24 = 24; + double field25 = 25; + double field26 = 26; + double field27 = 27; + double field28 = 28; + double field29 = 29; + double field30 = 30; + double field31 = 31; + double field32 = 32; + double field33 = 33; + double field34 = 34; + double field35 = 35; + double field36 = 36; + double field37 = 37; + double field38 = 38; + double field39 = 39; + double field40 = 40; + double field41 = 41; + double field42 = 42; + double field43 = 43; + double field44 = 44; + double field45 = 45; + double field46 = 46; + double field47 = 47; + double field48 = 48; + double field49 = 49; + double field50 = 50; + double field51 = 51; + double field52 = 52; + double field53 = 53; + double field54 = 54; + double field55 = 55; + double field56 = 56; + double field57 = 57; + double field58 = 58; + double field59 = 59; + double field60 = 60; + double field61 = 61; + double field62 = 62; + double field63 = 63; + double field64 = 64; + double field65 = 65; + double field66 = 66; + double field67 = 67; + double field68 = 68; + double field69 = 69; + double field70 = 70; + double field71 = 71; + double field72 = 72; + double field73 = 73; + double field74 = 74; + double field75 = 75; + double field76 = 76; + double field77 = 77; + double field78 = 78; + double field79 = 79; + double field80 = 80; + double field81 = 81; + double field82 = 82; + double field83 = 83; + double field84 = 84; + double field85 = 85; + double field86 = 86; + double field87 = 87; + double field88 = 88; + double field89 = 89; + double field90 = 90; + double field91 = 91; + double field92 = 92; + double field93 = 93; + double field94 = 94; + double field95 = 95; + double field96 = 96; + double field97 = 97; + double field98 = 98; + double field99 = 99; + double field100 = 100; +} \ No newline at end of file diff --git a/tests/assets/bigmessage_pb2.py b/tests/assets/bigmessage_pb2.py new file mode 100644 index 000000000..fe9844620 --- /dev/null +++ b/tests/assets/bigmessage_pb2.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: bigmessage.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10\x62igmessage.proto\x12\'ni.measurementlink.measurement.tests.v1\"\xa8\r\n\nBigMessage\x12\x0e\n\x06\x66ield1\x18\x01 \x01(\x01\x12\x0e\n\x06\x66ield2\x18\x02 \x01(\x01\x12\x0e\n\x06\x66ield3\x18\x03 \x01(\x01\x12\x0e\n\x06\x66ield4\x18\x04 \x01(\x01\x12\x0e\n\x06\x66ield5\x18\x05 \x01(\x01\x12\x0e\n\x06\x66ield6\x18\x06 \x01(\x01\x12\x0e\n\x06\x66ield7\x18\x07 \x01(\x01\x12\x0e\n\x06\x66ield8\x18\x08 \x01(\x01\x12\x0e\n\x06\x66ield9\x18\t \x01(\x01\x12\x0f\n\x07\x66ield10\x18\n \x01(\x01\x12\x0f\n\x07\x66ield11\x18\x0b \x01(\x01\x12\x0f\n\x07\x66ield12\x18\x0c \x01(\x01\x12\x0f\n\x07\x66ield13\x18\r \x01(\x01\x12\x0f\n\x07\x66ield14\x18\x0e \x01(\x01\x12\x0f\n\x07\x66ield15\x18\x0f \x01(\x01\x12\x0f\n\x07\x66ield16\x18\x10 \x01(\x01\x12\x0f\n\x07\x66ield17\x18\x11 \x01(\x01\x12\x0f\n\x07\x66ield18\x18\x12 \x01(\x01\x12\x0f\n\x07\x66ield19\x18\x13 \x01(\x01\x12\x0f\n\x07\x66ield20\x18\x14 \x01(\x01\x12\x0f\n\x07\x66ield21\x18\x15 \x01(\x01\x12\x0f\n\x07\x66ield22\x18\x16 \x01(\x01\x12\x0f\n\x07\x66ield23\x18\x17 \x01(\x01\x12\x0f\n\x07\x66ield24\x18\x18 \x01(\x01\x12\x0f\n\x07\x66ield25\x18\x19 \x01(\x01\x12\x0f\n\x07\x66ield26\x18\x1a \x01(\x01\x12\x0f\n\x07\x66ield27\x18\x1b \x01(\x01\x12\x0f\n\x07\x66ield28\x18\x1c \x01(\x01\x12\x0f\n\x07\x66ield29\x18\x1d \x01(\x01\x12\x0f\n\x07\x66ield30\x18\x1e \x01(\x01\x12\x0f\n\x07\x66ield31\x18\x1f \x01(\x01\x12\x0f\n\x07\x66ield32\x18 \x01(\x01\x12\x0f\n\x07\x66ield33\x18! \x01(\x01\x12\x0f\n\x07\x66ield34\x18\" \x01(\x01\x12\x0f\n\x07\x66ield35\x18# \x01(\x01\x12\x0f\n\x07\x66ield36\x18$ \x01(\x01\x12\x0f\n\x07\x66ield37\x18% \x01(\x01\x12\x0f\n\x07\x66ield38\x18& \x01(\x01\x12\x0f\n\x07\x66ield39\x18\' \x01(\x01\x12\x0f\n\x07\x66ield40\x18( \x01(\x01\x12\x0f\n\x07\x66ield41\x18) \x01(\x01\x12\x0f\n\x07\x66ield42\x18* \x01(\x01\x12\x0f\n\x07\x66ield43\x18+ \x01(\x01\x12\x0f\n\x07\x66ield44\x18, \x01(\x01\x12\x0f\n\x07\x66ield45\x18- \x01(\x01\x12\x0f\n\x07\x66ield46\x18. \x01(\x01\x12\x0f\n\x07\x66ield47\x18/ \x01(\x01\x12\x0f\n\x07\x66ield48\x18\x30 \x01(\x01\x12\x0f\n\x07\x66ield49\x18\x31 \x01(\x01\x12\x0f\n\x07\x66ield50\x18\x32 \x01(\x01\x12\x0f\n\x07\x66ield51\x18\x33 \x01(\x01\x12\x0f\n\x07\x66ield52\x18\x34 \x01(\x01\x12\x0f\n\x07\x66ield53\x18\x35 \x01(\x01\x12\x0f\n\x07\x66ield54\x18\x36 \x01(\x01\x12\x0f\n\x07\x66ield55\x18\x37 \x01(\x01\x12\x0f\n\x07\x66ield56\x18\x38 \x01(\x01\x12\x0f\n\x07\x66ield57\x18\x39 \x01(\x01\x12\x0f\n\x07\x66ield58\x18: \x01(\x01\x12\x0f\n\x07\x66ield59\x18; \x01(\x01\x12\x0f\n\x07\x66ield60\x18< \x01(\x01\x12\x0f\n\x07\x66ield61\x18= \x01(\x01\x12\x0f\n\x07\x66ield62\x18> \x01(\x01\x12\x0f\n\x07\x66ield63\x18? \x01(\x01\x12\x0f\n\x07\x66ield64\x18@ \x01(\x01\x12\x0f\n\x07\x66ield65\x18\x41 \x01(\x01\x12\x0f\n\x07\x66ield66\x18\x42 \x01(\x01\x12\x0f\n\x07\x66ield67\x18\x43 \x01(\x01\x12\x0f\n\x07\x66ield68\x18\x44 \x01(\x01\x12\x0f\n\x07\x66ield69\x18\x45 \x01(\x01\x12\x0f\n\x07\x66ield70\x18\x46 \x01(\x01\x12\x0f\n\x07\x66ield71\x18G \x01(\x01\x12\x0f\n\x07\x66ield72\x18H \x01(\x01\x12\x0f\n\x07\x66ield73\x18I \x01(\x01\x12\x0f\n\x07\x66ield74\x18J \x01(\x01\x12\x0f\n\x07\x66ield75\x18K \x01(\x01\x12\x0f\n\x07\x66ield76\x18L \x01(\x01\x12\x0f\n\x07\x66ield77\x18M \x01(\x01\x12\x0f\n\x07\x66ield78\x18N \x01(\x01\x12\x0f\n\x07\x66ield79\x18O \x01(\x01\x12\x0f\n\x07\x66ield80\x18P \x01(\x01\x12\x0f\n\x07\x66ield81\x18Q \x01(\x01\x12\x0f\n\x07\x66ield82\x18R \x01(\x01\x12\x0f\n\x07\x66ield83\x18S \x01(\x01\x12\x0f\n\x07\x66ield84\x18T \x01(\x01\x12\x0f\n\x07\x66ield85\x18U \x01(\x01\x12\x0f\n\x07\x66ield86\x18V \x01(\x01\x12\x0f\n\x07\x66ield87\x18W \x01(\x01\x12\x0f\n\x07\x66ield88\x18X \x01(\x01\x12\x0f\n\x07\x66ield89\x18Y \x01(\x01\x12\x0f\n\x07\x66ield90\x18Z \x01(\x01\x12\x0f\n\x07\x66ield91\x18[ \x01(\x01\x12\x0f\n\x07\x66ield92\x18\\ \x01(\x01\x12\x0f\n\x07\x66ield93\x18] \x01(\x01\x12\x0f\n\x07\x66ield94\x18^ \x01(\x01\x12\x0f\n\x07\x66ield95\x18_ \x01(\x01\x12\x0f\n\x07\x66ield96\x18` \x01(\x01\x12\x0f\n\x07\x66ield97\x18\x61 \x01(\x01\x12\x0f\n\x07\x66ield98\x18\x62 \x01(\x01\x12\x0f\n\x07\x66ield99\x18\x63 \x01(\x01\x12\x10\n\x08\x66ield100\x18\x64 \x01(\x01\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'bigmessage_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + _BIGMESSAGE._serialized_start=62 + _BIGMESSAGE._serialized_end=1766 +# @@protoc_insertion_point(module_scope) diff --git a/tests/assets/bigmessage_pb2.pyi b/tests/assets/bigmessage_pb2.pyi new file mode 100644 index 000000000..518b4c920 --- /dev/null +++ b/tests/assets/bigmessage_pb2.pyi @@ -0,0 +1,327 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" +import builtins +import google.protobuf.descriptor +import google.protobuf.message +import sys + +if sys.version_info >= (3, 8): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing_extensions.final +class BigMessage(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + FIELD1_FIELD_NUMBER: builtins.int + FIELD2_FIELD_NUMBER: builtins.int + FIELD3_FIELD_NUMBER: builtins.int + FIELD4_FIELD_NUMBER: builtins.int + FIELD5_FIELD_NUMBER: builtins.int + FIELD6_FIELD_NUMBER: builtins.int + FIELD7_FIELD_NUMBER: builtins.int + FIELD8_FIELD_NUMBER: builtins.int + FIELD9_FIELD_NUMBER: builtins.int + FIELD10_FIELD_NUMBER: builtins.int + FIELD11_FIELD_NUMBER: builtins.int + FIELD12_FIELD_NUMBER: builtins.int + FIELD13_FIELD_NUMBER: builtins.int + FIELD14_FIELD_NUMBER: builtins.int + FIELD15_FIELD_NUMBER: builtins.int + FIELD16_FIELD_NUMBER: builtins.int + FIELD17_FIELD_NUMBER: builtins.int + FIELD18_FIELD_NUMBER: builtins.int + FIELD19_FIELD_NUMBER: builtins.int + FIELD20_FIELD_NUMBER: builtins.int + FIELD21_FIELD_NUMBER: builtins.int + FIELD22_FIELD_NUMBER: builtins.int + FIELD23_FIELD_NUMBER: builtins.int + FIELD24_FIELD_NUMBER: builtins.int + FIELD25_FIELD_NUMBER: builtins.int + FIELD26_FIELD_NUMBER: builtins.int + FIELD27_FIELD_NUMBER: builtins.int + FIELD28_FIELD_NUMBER: builtins.int + FIELD29_FIELD_NUMBER: builtins.int + FIELD30_FIELD_NUMBER: builtins.int + FIELD31_FIELD_NUMBER: builtins.int + FIELD32_FIELD_NUMBER: builtins.int + FIELD33_FIELD_NUMBER: builtins.int + FIELD34_FIELD_NUMBER: builtins.int + FIELD35_FIELD_NUMBER: builtins.int + FIELD36_FIELD_NUMBER: builtins.int + FIELD37_FIELD_NUMBER: builtins.int + FIELD38_FIELD_NUMBER: builtins.int + FIELD39_FIELD_NUMBER: builtins.int + FIELD40_FIELD_NUMBER: builtins.int + FIELD41_FIELD_NUMBER: builtins.int + FIELD42_FIELD_NUMBER: builtins.int + FIELD43_FIELD_NUMBER: builtins.int + FIELD44_FIELD_NUMBER: builtins.int + FIELD45_FIELD_NUMBER: builtins.int + FIELD46_FIELD_NUMBER: builtins.int + FIELD47_FIELD_NUMBER: builtins.int + FIELD48_FIELD_NUMBER: builtins.int + FIELD49_FIELD_NUMBER: builtins.int + FIELD50_FIELD_NUMBER: builtins.int + FIELD51_FIELD_NUMBER: builtins.int + FIELD52_FIELD_NUMBER: builtins.int + FIELD53_FIELD_NUMBER: builtins.int + FIELD54_FIELD_NUMBER: builtins.int + FIELD55_FIELD_NUMBER: builtins.int + FIELD56_FIELD_NUMBER: builtins.int + FIELD57_FIELD_NUMBER: builtins.int + FIELD58_FIELD_NUMBER: builtins.int + FIELD59_FIELD_NUMBER: builtins.int + FIELD60_FIELD_NUMBER: builtins.int + FIELD61_FIELD_NUMBER: builtins.int + FIELD62_FIELD_NUMBER: builtins.int + FIELD63_FIELD_NUMBER: builtins.int + FIELD64_FIELD_NUMBER: builtins.int + FIELD65_FIELD_NUMBER: builtins.int + FIELD66_FIELD_NUMBER: builtins.int + FIELD67_FIELD_NUMBER: builtins.int + FIELD68_FIELD_NUMBER: builtins.int + FIELD69_FIELD_NUMBER: builtins.int + FIELD70_FIELD_NUMBER: builtins.int + FIELD71_FIELD_NUMBER: builtins.int + FIELD72_FIELD_NUMBER: builtins.int + FIELD73_FIELD_NUMBER: builtins.int + FIELD74_FIELD_NUMBER: builtins.int + FIELD75_FIELD_NUMBER: builtins.int + FIELD76_FIELD_NUMBER: builtins.int + FIELD77_FIELD_NUMBER: builtins.int + FIELD78_FIELD_NUMBER: builtins.int + FIELD79_FIELD_NUMBER: builtins.int + FIELD80_FIELD_NUMBER: builtins.int + FIELD81_FIELD_NUMBER: builtins.int + FIELD82_FIELD_NUMBER: builtins.int + FIELD83_FIELD_NUMBER: builtins.int + FIELD84_FIELD_NUMBER: builtins.int + FIELD85_FIELD_NUMBER: builtins.int + FIELD86_FIELD_NUMBER: builtins.int + FIELD87_FIELD_NUMBER: builtins.int + FIELD88_FIELD_NUMBER: builtins.int + FIELD89_FIELD_NUMBER: builtins.int + FIELD90_FIELD_NUMBER: builtins.int + FIELD91_FIELD_NUMBER: builtins.int + FIELD92_FIELD_NUMBER: builtins.int + FIELD93_FIELD_NUMBER: builtins.int + FIELD94_FIELD_NUMBER: builtins.int + FIELD95_FIELD_NUMBER: builtins.int + FIELD96_FIELD_NUMBER: builtins.int + FIELD97_FIELD_NUMBER: builtins.int + FIELD98_FIELD_NUMBER: builtins.int + FIELD99_FIELD_NUMBER: builtins.int + FIELD100_FIELD_NUMBER: builtins.int + field1: builtins.float + field2: builtins.float + field3: builtins.float + field4: builtins.float + field5: builtins.float + field6: builtins.float + field7: builtins.float + field8: builtins.float + field9: builtins.float + field10: builtins.float + field11: builtins.float + field12: builtins.float + field13: builtins.float + field14: builtins.float + field15: builtins.float + field16: builtins.float + field17: builtins.float + field18: builtins.float + field19: builtins.float + field20: builtins.float + field21: builtins.float + field22: builtins.float + field23: builtins.float + field24: builtins.float + field25: builtins.float + field26: builtins.float + field27: builtins.float + field28: builtins.float + field29: builtins.float + field30: builtins.float + field31: builtins.float + field32: builtins.float + field33: builtins.float + field34: builtins.float + field35: builtins.float + field36: builtins.float + field37: builtins.float + field38: builtins.float + field39: builtins.float + field40: builtins.float + field41: builtins.float + field42: builtins.float + field43: builtins.float + field44: builtins.float + field45: builtins.float + field46: builtins.float + field47: builtins.float + field48: builtins.float + field49: builtins.float + field50: builtins.float + field51: builtins.float + field52: builtins.float + field53: builtins.float + field54: builtins.float + field55: builtins.float + field56: builtins.float + field57: builtins.float + field58: builtins.float + field59: builtins.float + field60: builtins.float + field61: builtins.float + field62: builtins.float + field63: builtins.float + field64: builtins.float + field65: builtins.float + field66: builtins.float + field67: builtins.float + field68: builtins.float + field69: builtins.float + field70: builtins.float + field71: builtins.float + field72: builtins.float + field73: builtins.float + field74: builtins.float + field75: builtins.float + field76: builtins.float + field77: builtins.float + field78: builtins.float + field79: builtins.float + field80: builtins.float + field81: builtins.float + field82: builtins.float + field83: builtins.float + field84: builtins.float + field85: builtins.float + field86: builtins.float + field87: builtins.float + field88: builtins.float + field89: builtins.float + field90: builtins.float + field91: builtins.float + field92: builtins.float + field93: builtins.float + field94: builtins.float + field95: builtins.float + field96: builtins.float + field97: builtins.float + field98: builtins.float + field99: builtins.float + field100: builtins.float + def __init__( + self, + *, + field1: builtins.float = ..., + field2: builtins.float = ..., + field3: builtins.float = ..., + field4: builtins.float = ..., + field5: builtins.float = ..., + field6: builtins.float = ..., + field7: builtins.float = ..., + field8: builtins.float = ..., + field9: builtins.float = ..., + field10: builtins.float = ..., + field11: builtins.float = ..., + field12: builtins.float = ..., + field13: builtins.float = ..., + field14: builtins.float = ..., + field15: builtins.float = ..., + field16: builtins.float = ..., + field17: builtins.float = ..., + field18: builtins.float = ..., + field19: builtins.float = ..., + field20: builtins.float = ..., + field21: builtins.float = ..., + field22: builtins.float = ..., + field23: builtins.float = ..., + field24: builtins.float = ..., + field25: builtins.float = ..., + field26: builtins.float = ..., + field27: builtins.float = ..., + field28: builtins.float = ..., + field29: builtins.float = ..., + field30: builtins.float = ..., + field31: builtins.float = ..., + field32: builtins.float = ..., + field33: builtins.float = ..., + field34: builtins.float = ..., + field35: builtins.float = ..., + field36: builtins.float = ..., + field37: builtins.float = ..., + field38: builtins.float = ..., + field39: builtins.float = ..., + field40: builtins.float = ..., + field41: builtins.float = ..., + field42: builtins.float = ..., + field43: builtins.float = ..., + field44: builtins.float = ..., + field45: builtins.float = ..., + field46: builtins.float = ..., + field47: builtins.float = ..., + field48: builtins.float = ..., + field49: builtins.float = ..., + field50: builtins.float = ..., + field51: builtins.float = ..., + field52: builtins.float = ..., + field53: builtins.float = ..., + field54: builtins.float = ..., + field55: builtins.float = ..., + field56: builtins.float = ..., + field57: builtins.float = ..., + field58: builtins.float = ..., + field59: builtins.float = ..., + field60: builtins.float = ..., + field61: builtins.float = ..., + field62: builtins.float = ..., + field63: builtins.float = ..., + field64: builtins.float = ..., + field65: builtins.float = ..., + field66: builtins.float = ..., + field67: builtins.float = ..., + field68: builtins.float = ..., + field69: builtins.float = ..., + field70: builtins.float = ..., + field71: builtins.float = ..., + field72: builtins.float = ..., + field73: builtins.float = ..., + field74: builtins.float = ..., + field75: builtins.float = ..., + field76: builtins.float = ..., + field77: builtins.float = ..., + field78: builtins.float = ..., + field79: builtins.float = ..., + field80: builtins.float = ..., + field81: builtins.float = ..., + field82: builtins.float = ..., + field83: builtins.float = ..., + field84: builtins.float = ..., + field85: builtins.float = ..., + field86: builtins.float = ..., + field87: builtins.float = ..., + field88: builtins.float = ..., + field89: builtins.float = ..., + field90: builtins.float = ..., + field91: builtins.float = ..., + field92: builtins.float = ..., + field93: builtins.float = ..., + field94: builtins.float = ..., + field95: builtins.float = ..., + field96: builtins.float = ..., + field97: builtins.float = ..., + field98: builtins.float = ..., + field99: builtins.float = ..., + field100: builtins.float = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["field1", b"field1", "field10", b"field10", "field100", b"field100", "field11", b"field11", "field12", b"field12", "field13", b"field13", "field14", b"field14", "field15", b"field15", "field16", b"field16", "field17", b"field17", "field18", b"field18", "field19", b"field19", "field2", b"field2", "field20", b"field20", "field21", b"field21", "field22", b"field22", "field23", b"field23", "field24", b"field24", "field25", b"field25", "field26", b"field26", "field27", b"field27", "field28", b"field28", "field29", b"field29", "field3", b"field3", "field30", b"field30", "field31", b"field31", "field32", b"field32", "field33", b"field33", "field34", b"field34", "field35", b"field35", "field36", b"field36", "field37", b"field37", "field38", b"field38", "field39", b"field39", "field4", b"field4", "field40", b"field40", "field41", b"field41", "field42", b"field42", "field43", b"field43", "field44", b"field44", "field45", b"field45", "field46", b"field46", "field47", b"field47", "field48", b"field48", "field49", b"field49", "field5", b"field5", "field50", b"field50", "field51", b"field51", "field52", b"field52", "field53", b"field53", "field54", b"field54", "field55", b"field55", "field56", b"field56", "field57", b"field57", "field58", b"field58", "field59", b"field59", "field6", b"field6", "field60", b"field60", "field61", b"field61", "field62", b"field62", "field63", b"field63", "field64", b"field64", "field65", b"field65", "field66", b"field66", "field67", b"field67", "field68", b"field68", "field69", b"field69", "field7", b"field7", "field70", b"field70", "field71", b"field71", "field72", b"field72", "field73", b"field73", "field74", b"field74", "field75", b"field75", "field76", b"field76", "field77", b"field77", "field78", b"field78", "field79", b"field79", "field8", b"field8", "field80", b"field80", "field81", b"field81", "field82", b"field82", "field83", b"field83", "field84", b"field84", "field85", b"field85", "field86", b"field86", "field87", b"field87", "field88", b"field88", "field89", b"field89", "field9", b"field9", "field90", b"field90", "field91", b"field91", "field92", b"field92", "field93", b"field93", "field94", b"field94", "field95", b"field95", "field96", b"field96", "field97", b"field97", "field98", b"field98", "field99", b"field99"]) -> None: ... + +global___BigMessage = BigMessage diff --git a/tests/assets/bigmessage_pb2_grpc.py b/tests/assets/bigmessage_pb2_grpc.py new file mode 100644 index 000000000..2daafffeb --- /dev/null +++ b/tests/assets/bigmessage_pb2_grpc.py @@ -0,0 +1,4 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + diff --git a/tests/assets/bigmessage_pb2_grpc.pyi b/tests/assets/bigmessage_pb2_grpc.pyi new file mode 100644 index 000000000..b13382f6a --- /dev/null +++ b/tests/assets/bigmessage_pb2_grpc.pyi @@ -0,0 +1,17 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" +import abc +import collections.abc +import grpc +import grpc.aio +import typing + +_T = typing.TypeVar('_T') + +class _MaybeAsyncIterator(collections.abc.AsyncIterator[_T], collections.abc.Iterator[_T], metaclass=abc.ABCMeta): + ... + +class _ServicerContext(grpc.ServicerContext, grpc.aio.ServicerContext): # type: ignore + ... diff --git a/tests/unit/test_serializer.py b/tests/unit/test_serializer.py index 63b9c2c42..e2f914714 100644 --- a/tests/unit/test_serializer.py +++ b/tests/unit/test_serializer.py @@ -1,5 +1,6 @@ """Contains tests to validate serializer.py.""" from enum import Enum, IntEnum +from typing import Dict, Sequence import pytest from google.protobuf import any_pb2, type_pb2 @@ -11,6 +12,7 @@ ) from ni_measurementlink_service._internal.stubs.ni.protobuf.types import xydata_pb2 from tests.assets import test_pb2 +from tests.assets.bigmessage_pb2 import BigMessage class DifferentColor(Enum): @@ -35,6 +37,9 @@ class Countries(IntEnum): double_xy_data.x_data.append(4) double_xy_data.y_data.append(6) +# This should match the number of fields in bigmessage.proto. +BIG_MESSAGE_SIZE = 100 + @pytest.mark.parametrize( "test_values", @@ -237,6 +242,31 @@ def test___empty_buffer___deserialize_parameters___returns_zero_or_empty(): assert value == 0 +def test___big_message___deserialize_parameters___returns_parameter_value_by_id() -> None: + parameter_metadata_by_id = _get_big_message_metadata_by_id() + values = [123.456 + i for i in range(BIG_MESSAGE_SIZE)] + message = _get_big_message(values) + serialized_data = message.SerializeToString() + expected_parameter_value_by_id = {i + 1: value for (i, value) in enumerate(values)} + + parameter_value_by_id = serializer.deserialize_parameters( + parameter_metadata_by_id, serialized_data + ) + + assert parameter_value_by_id == pytest.approx(expected_parameter_value_by_id) + + +def test___big_message___serialize_parameters___returns_serialized_data() -> None: + parameter_metadata_by_id = _get_big_message_metadata_by_id() + values = [123.456 + i for i in range(BIG_MESSAGE_SIZE)] + expected_message = _get_big_message(values) + + serialized_data = serializer.serialize_parameters(parameter_metadata_by_id, values) + + message = BigMessage.FromString(serialized_data) + assert message.ListFields() == pytest.approx(expected_message.ListFields()) + + def _validate_serialized_bytes(custom_serialized_bytes, values): # Serialization using gRPC Any grpc_serialized_data = _get_grpc_serialized_data(values) @@ -442,3 +472,22 @@ def _get_test_grpc_message(test_values): parameter.xy_data.x_data.append(test_values[20].x_data[0]) parameter.xy_data.y_data.append(test_values[20].y_data[0]) return parameter + + +def _get_big_message_metadata_by_id() -> Dict[int, ParameterMetadata]: + return { + i + + 1: ParameterMetadata( + display_name=f"field{i + 1}", + type=type_pb2.Field.TYPE_DOUBLE, + repeated=False, + default_value=-1.0, + annotations={}, + ) + for i in range(BIG_MESSAGE_SIZE) + } + + +def _get_big_message(values: Sequence[float]) -> BigMessage: + assert len(values) == BIG_MESSAGE_SIZE + return BigMessage(**{f"field{i + 1}": value for (i, value) in enumerate(values)})