Skip to content

Commit

Permalink
Fix missing type check for arguments of parameterized messages
Browse files Browse the repository at this point in the history
Ref. #1104
  • Loading branch information
treiher committed Jul 12, 2022
1 parent 79c2ae8 commit fd08903
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ PyRFLX:

- Error caused by relations between sequences, opaque fields or aggregates (#964)
- Undefined attribute in `MessageValue.Field` (#1045)
- Missing type check for arguments of parameterized message (#1104)

## [0.5.0] - 2021-08-11

Expand Down
40 changes: 28 additions & 12 deletions rflx/pyrflx/typevalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
)
from rflx.identifier import ID
from rflx.model import (
BOOLEAN,
FINAL,
INITIAL,
ByteOrder,
Expand Down Expand Up @@ -602,6 +603,23 @@ def add_refinement(self, refinement: "RefinementValue") -> None:
self._refinements = [*(self._refinements or []), refinement]

def add_parameters(self, parameters: ty.Mapping[str, ty.Union[bool, int, str]]) -> None:
expected = set(p.name for p in self._type.parameter_types.keys())
added = set(p for p in parameters)

if expected - added:
message = ", ".join(expected - added)
raise PyRFLXError(f"missing parameter values: {message}")

if added - expected:
message = ", ".join(added - expected)
raise PyRFLXError(f"unexpected parameter values: {message}")

def check_type(valid: bool) -> None:
if not valid:
raise PyRFLXError(
f'message argument for "{name}" has invalid type "{type(value).__name__}"'
)

enum_literals = {
str(l): str(t.package * l)
for t in self._type.types.values()
Expand All @@ -612,29 +630,27 @@ def add_parameters(self, parameters: ty.Mapping[str, ty.Union[bool, int, str]])
expr: Expr
for name, value in parameters.items():
if isinstance(value, bool):
check_type(self.model.parameter_types[Field(name)] == BOOLEAN)
expr = TRUE if value else FALSE
elif isinstance(value, int):
check_type(isinstance(self.model.parameter_types[Field(name)], Integer))
expr = Number(value)
elif isinstance(value, str):
check_type(
isinstance(self.model.parameter_types[Field(name)], Enumeration)
and self.model.parameter_types[Field(name)] != BOOLEAN
)
if value in enum_literals:
expr = Literal(enum_literals[value])
else:
assert value in enum_literals.values()
expr = Literal(value)
else:
raise PyRFLXError(f"{type(value)} is no supported parameter type")
params[Variable(name)] = expr

expected = set(p.name for p in self._type.parameter_types.keys())
added = set(p.name for p in params if isinstance(p, Variable))

if expected - added:
message = ", ".join(expected - added)
raise PyRFLXError(f"missing parameter values: {message}")
raise PyRFLXError(
f'message argument for "{name}" has unsupported type "{type(value).__name__}"'
)

if added - expected:
message = ", ".join(added - expected)
raise PyRFLXError(f"unexpected parameter values: {message}")
params[Variable(name)] = expr

self._parameters = params
if not self._skip_verification:
Expand Down
37 changes: 35 additions & 2 deletions tests/unit/pyrflx_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1426,13 +1426,46 @@ def test_parameterized_message_no_verification() -> None:
assert message_unv.bytestring == bytes(8)


def test_parameterized_message_unsupported_type(parameterized_package: Package) -> None:
with pytest.raises(
PyRFLXError,
match='^pyrflx: error: message argument for "Length" has unsupported type "bytes"$',
):
parameterized_package.new_message(
"Message",
{
"Length": bytes(8), # type: ignore[dict-item]
"Tag_Mode": "Without_Tag",
"Tag_Value": "Parameterized::Tag_A",
"Use_Tag": True,
},
)


def test_parameterized_message_invalid_type(parameterized_package: Package) -> None:
with pytest.raises(
PyRFLXError, match=f"^pyrflx: error: {type(bytes())} is no supported parameter type$"
PyRFLXError, match='^pyrflx: error: message argument for "Tag_Mode" has invalid type "int"$'
):
parameterized_package.new_message(
"Message",
{"Length": bytes(8)}, # type: ignore[dict-item]
{
"Length": 8,
"Tag_Mode": 2,
"Tag_Value": "Parameterized::Tag_A",
"Use_Tag": True,
},
)
with pytest.raises(
PyRFLXError, match='^pyrflx: error: message argument for "Use_Tag" has invalid type "str"$'
):
parameterized_package.new_message(
"Message",
{
"Length": 8,
"Tag_Mode": "Without_Tag",
"Tag_Value": "Parameterized::Tag_A",
"Use_Tag": "True",
},
)


Expand Down

0 comments on commit fd08903

Please sign in to comment.