From 81128f38b32f0749b178506c32531950e805c553 Mon Sep 17 00:00:00 2001 From: Michael Johansen Date: Tue, 17 Jun 2025 12:52:56 -0500 Subject: [PATCH 1/4] Add a unit test. It's still failing, but I'll come back to it. Signed-off-by: Michael Johansen --- tests/unit/test_convert.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/unit/test_convert.py diff --git a/tests/unit/test_convert.py b/tests/unit/test_convert.py new file mode 100644 index 0000000..7d1904c --- /dev/null +++ b/tests/unit/test_convert.py @@ -0,0 +1,21 @@ +import pytest +from ni.protobuf.types.scalar_pb2 import ScalarData +from nitypes.scalar import Scalar + +import nipanel._convert +from google.protobuf import any_pb2, wrappers_pb2 +from nipanel.converters.protobuf_types import ScalarConverter + + +# ======================================================== +# Protobuf to Python +# ======================================================== +def test___bool___to_any___valid_bool_value() -> None: + expected_bool = True + + result = nipanel._convert.to_any(expected_bool) + + assert isinstance(result, any_pb2.Any) + any_proto = any_pb2.Any() + assert isinstance(result, wrappers_pb2.BoolValue) + assert result. From 2e5f07901eed3e8713d2f80123c3aa136d517b0d Mon Sep 17 00:00:00 2001 From: Michael Johansen Date: Tue, 17 Jun 2025 16:38:11 -0500 Subject: [PATCH 2/4] Got two tests working. Signed-off-by: Michael Johansen --- tests/unit/test_convert.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tests/unit/test_convert.py b/tests/unit/test_convert.py index 7d1904c..1d03cac 100644 --- a/tests/unit/test_convert.py +++ b/tests/unit/test_convert.py @@ -4,7 +4,6 @@ import nipanel._convert from google.protobuf import any_pb2, wrappers_pb2 -from nipanel.converters.protobuf_types import ScalarConverter # ======================================================== @@ -14,8 +13,26 @@ def test___bool___to_any___valid_bool_value() -> None: expected_bool = True result = nipanel._convert.to_any(expected_bool) + unpack_dest = wrappers_pb2.BoolValue(value=False) + _assert_any_and_unpack(result, unpack_dest) - assert isinstance(result, any_pb2.Any) - any_proto = any_pb2.Any() - assert isinstance(result, wrappers_pb2.BoolValue) - assert result. + assert isinstance(unpack_dest, wrappers_pb2.BoolValue) + assert unpack_dest.value == expected_bool + + +def test___int___to_any___valid_int_value() -> None: + expected_int = 123 + + result = nipanel._convert.to_any(expected_int) + unpack_dest = wrappers_pb2.Int64Value(value=0) + _assert_any_and_unpack(result, unpack_dest) + + assert isinstance(unpack_dest, wrappers_pb2.Int64Value) + assert unpack_dest.value == expected_int + + +def _assert_any_and_unpack(packed_message, unpack_destination): + assert isinstance(packed_message, any_pb2.Any) + did_unpack = packed_message.Unpack(unpack_destination) + if not did_unpack: + raise ValueError(f"Failed to unpack Any with type '{packed_message.TypeName()}'") From 92479b75c608e4e844733d846c438953303e654e Mon Sep 17 00:00:00 2001 From: Michael Johansen Date: Thu, 19 Jun 2025 09:43:34 -0500 Subject: [PATCH 3/4] Add unit tests for _convert.to_any() and from_any() Signed-off-by: Michael Johansen --- tests/unit/test_convert.py | 131 ++++++++++++++++++++++++++++++++----- 1 file changed, 113 insertions(+), 18 deletions(-) diff --git a/tests/unit/test_convert.py b/tests/unit/test_convert.py index 1d03cac..f3a2830 100644 --- a/tests/unit/test_convert.py +++ b/tests/unit/test_convert.py @@ -1,38 +1,133 @@ +from typing import Any, Type, Union + import pytest -from ni.protobuf.types.scalar_pb2 import ScalarData -from nitypes.scalar import Scalar +from google.protobuf import any_pb2, wrappers_pb2 +from ni.pythonpanel.v1 import python_panel_types_pb2 +from typing_extensions import TypeAlias import nipanel._convert -from google.protobuf import any_pb2, wrappers_pb2 + + +_AnyWrappersPb2: TypeAlias = Union[ + wrappers_pb2.BoolValue, + wrappers_pb2.BytesValue, + wrappers_pb2.DoubleValue, + wrappers_pb2.Int64Value, + wrappers_pb2.StringValue, +] + +_AnyPanelPbTypes: TypeAlias = Union[ + python_panel_types_pb2.BoolCollection, + python_panel_types_pb2.ByteStringCollection, + python_panel_types_pb2.FloatCollection, + python_panel_types_pb2.IntCollection, + python_panel_types_pb2.StringCollection, +] # ======================================================== -# Protobuf to Python +# Python to Protobuf # ======================================================== -def test___bool___to_any___valid_bool_value() -> None: - expected_bool = True +@pytest.mark.parametrize( + "proto_type, default_value, expected_value", + [ + (wrappers_pb2.BoolValue, False, True), + (wrappers_pb2.BytesValue, b"", b"mystr"), + (wrappers_pb2.DoubleValue, 0.0, 456.2), + (wrappers_pb2.Int64Value, 0, 123), + (wrappers_pb2.StringValue, "", "mystr"), + ], +) +def test___python_builtin_scalar___to_any___valid_wrapperpb2_value( + proto_type: Type[_AnyWrappersPb2], default_value: Any, expected_value: Any +) -> None: + result = nipanel._convert.to_any(expected_value) + unpack_dest = proto_type(value=default_value) + _assert_any_and_unpack(result, unpack_dest) + + assert isinstance(unpack_dest, proto_type) + assert unpack_dest.value == expected_value - result = nipanel._convert.to_any(expected_bool) - unpack_dest = wrappers_pb2.BoolValue(value=False) + +@pytest.mark.parametrize( + "proto_type, default_value, expected_value", + [ + (python_panel_types_pb2.BoolCollection, [False, False, False], [True, True, True]), + (python_panel_types_pb2.ByteStringCollection, [b"", b"", b""], [b"a", b"b", b"c"]), + (python_panel_types_pb2.FloatCollection, [0.0, 0.0, 0.0], [1.0, 2.0, 3.0]), + (python_panel_types_pb2.IntCollection, [0, 0, 0], [1, 2, 3]), + (python_panel_types_pb2.StringCollection, ["", "", ""], ["a", "b", "c"]), + ], +) +def test___python_panel_collection___to_any___valid_paneltype_value( + proto_type: Type[_AnyPanelPbTypes], default_value: Any, expected_value: Any +) -> None: + result = nipanel._convert.to_any(expected_value) + unpack_dest = proto_type(values=default_value) _assert_any_and_unpack(result, unpack_dest) - assert isinstance(unpack_dest, wrappers_pb2.BoolValue) - assert unpack_dest.value == expected_bool + assert isinstance(unpack_dest, proto_type) + assert unpack_dest.values == expected_value + +# ======================================================== +# Protobuf to Python +# ======================================================== +@pytest.mark.parametrize( + "proto_type, expected_value", + [ + (wrappers_pb2.BoolValue, True), + (wrappers_pb2.BytesValue, b"mystr"), + (wrappers_pb2.DoubleValue, 456.2), + (wrappers_pb2.Int64Value, 123), + (wrappers_pb2.StringValue, "mystr"), + ], +) +def test___wrapperpb2_value___from_any___valid_python_value( + proto_type: Type[_AnyWrappersPb2], expected_value: Any +) -> None: + pb_value = proto_type(value=expected_value) + packed_any = _pack_into_any(pb_value) -def test___int___to_any___valid_int_value() -> None: - expected_int = 123 + result = nipanel._convert.from_any(packed_any) - result = nipanel._convert.to_any(expected_int) - unpack_dest = wrappers_pb2.Int64Value(value=0) - _assert_any_and_unpack(result, unpack_dest) + assert isinstance(result, type(expected_value)) + assert result == expected_value + + +@pytest.mark.parametrize( + "proto_type, expected_value", + [ + (python_panel_types_pb2.BoolCollection, [True, True, True]), + (python_panel_types_pb2.ByteStringCollection, [b"a", b"b", b"c"]), + (python_panel_types_pb2.FloatCollection, [1.0, 2.0, 3.0]), + (python_panel_types_pb2.IntCollection, [1, 2, 3]), + (python_panel_types_pb2.StringCollection, ["a", "b", "c"]), + ], +) +def test___paneltype_value___from_any___valid_python_value( + proto_type: Type[_AnyPanelPbTypes], expected_value: Any +) -> None: + pb_value = proto_type(values=expected_value) + packed_any = _pack_into_any(pb_value) - assert isinstance(unpack_dest, wrappers_pb2.Int64Value) - assert unpack_dest.value == expected_int + result = nipanel._convert.from_any(packed_any) + assert isinstance(result, type(expected_value)) + assert result == expected_value -def _assert_any_and_unpack(packed_message, unpack_destination): + +# ======================================================== +# Pack/Unpack Helpers +# ======================================================== +def _assert_any_and_unpack(packed_message: any_pb2.Any, unpack_destination: Any) -> None: assert isinstance(packed_message, any_pb2.Any) did_unpack = packed_message.Unpack(unpack_destination) if not did_unpack: raise ValueError(f"Failed to unpack Any with type '{packed_message.TypeName()}'") + + +def _pack_into_any(proto_value: Union[_AnyWrappersPb2, _AnyPanelPbTypes]) -> any_pb2.Any: + as_any = any_pb2.Any() + as_any.Pack(proto_value) + return as_any From 4ffcd2c1295c6ef00f512519fd4527d0291830c0 Mon Sep 17 00:00:00 2001 From: Michael Johansen Date: Thu, 19 Jun 2025 10:29:40 -0500 Subject: [PATCH 4/4] Change to use assert for Unpack. Signed-off-by: Michael Johansen --- tests/unit/test_convert.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/unit/test_convert.py b/tests/unit/test_convert.py index f3a2830..a14a359 100644 --- a/tests/unit/test_convert.py +++ b/tests/unit/test_convert.py @@ -122,9 +122,7 @@ def test___paneltype_value___from_any___valid_python_value( # ======================================================== def _assert_any_and_unpack(packed_message: any_pb2.Any, unpack_destination: Any) -> None: assert isinstance(packed_message, any_pb2.Any) - did_unpack = packed_message.Unpack(unpack_destination) - if not did_unpack: - raise ValueError(f"Failed to unpack Any with type '{packed_message.TypeName()}'") + assert packed_message.Unpack(unpack_destination) def _pack_into_any(proto_value: Union[_AnyWrappersPb2, _AnyPanelPbTypes]) -> any_pb2.Any: