Skip to content

Commit

Permalink
Improve errors for SetScratchpadTargetAndActionRequest.from_payload()
Browse files Browse the repository at this point in the history
If constructing a new SetScratchpadTargetAndActionRequest from payload
fails due to invalid values, a new InvalidMessageContents exception is
raised. This exception can hold the header of the request message, and
it would be possible to generate a response with the corresponding
req_id based on the exception.
  • Loading branch information
sgunes-wirepas committed Nov 22, 2024
1 parent afa7ad0 commit 400b1e8
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 6 deletions.
82 changes: 81 additions & 1 deletion tests/test_set_scratchpad_target.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
# flake8: noqa

import wirepas_mesh_messaging
import enum

import pytest
from default_value import *

import wirepas_mesh_messaging
from wirepas_mesh_messaging.proto.generic_message_pb2 import GenericMessage
from wirepas_mesh_messaging.wirepas_exceptions import InvalidMessageContents


def test_generate_parse_request_with_raw():
request = wirepas_mesh_messaging.SetScratchpadTargetAndActionRequest(
Expand Down Expand Up @@ -62,3 +67,78 @@ def test_generate_parse_response():
assert v.value == request2.__dict__[k].value
else:
assert v == request2.__dict__[k]


def test_constructing_request_with_too_large_target_sequence_should_fail():
target_and_action = {
"action": wirepas_mesh_messaging.ScratchpadAction.ACTION_PROPAGATE_ONLY,
"target_sequence": 0x100,
}
with pytest.raises(ValueError):
wirepas_mesh_messaging.SetScratchpadTargetAndActionRequest(
SINK_ID, target_and_action, REQUEST_ID
)


def test_constructing_request_with_too_large_target_crc_should_fail():
target_and_action = {
"action": wirepas_mesh_messaging.ScratchpadAction.ACTION_PROPAGATE_ONLY,
"target_crc": 0x10000,
}
with pytest.raises(ValueError):
wirepas_mesh_messaging.SetScratchpadTargetAndActionRequest(
SINK_ID, target_and_action, REQUEST_ID
)


def test_constructing_request_with_too_large_raw_action_should_fail():
target_and_action = {
"action": wirepas_mesh_messaging.ScratchpadAction.ACTION_PROPAGATE_AND_PROCESS,
"param": 0x100,
}
with pytest.raises(ValueError):
wirepas_mesh_messaging.SetScratchpadTargetAndActionRequest(
SINK_ID, target_and_action, REQUEST_ID
)


def test_decoding_request_with_too_large_target_sequence_should_fail_with_correct_exception():
TEST_TIME = 34567
base_request = wirepas_mesh_messaging.SetScratchpadTargetAndActionRequest(
SINK_ID, SCRATCHPAD_TARGET_RAW, REQUEST_ID, time_ms_epoch=TEST_TIME
)
message = GenericMessage()
message.ParseFromString(base_request.payload)
message.wirepas.set_scratchpad_target_and_action_req.target_and_action.target_sequence = (
0x100
)
test_payload = message.SerializeToString()

with pytest.raises(InvalidMessageContents) as exc_info:
wirepas_mesh_messaging.SetScratchpadTargetAndActionRequest.from_payload(
test_payload
)
assert exc_info.value.header["req_id"] == REQUEST_ID
assert exc_info.value.header["sink_id"] == SINK_ID
assert exc_info.value.header["time_ms_epoch"] == TEST_TIME


def test_decoding_request_with_too_large_target_crc_should_fail_with_correct_exception():
TEST_TIME = 1234567
base_request = wirepas_mesh_messaging.SetScratchpadTargetAndActionRequest(
SINK_ID_2, SCRATCHPAD_TARGET_RAW, REQUEST_ID, time_ms_epoch=TEST_TIME
)
message = GenericMessage()
message.ParseFromString(base_request.payload)
message.wirepas.set_scratchpad_target_and_action_req.target_and_action.target_crc = (
0x10000
)
test_payload = message.SerializeToString()

with pytest.raises(InvalidMessageContents) as exc_info:
wirepas_mesh_messaging.SetScratchpadTargetAndActionRequest.from_payload(
test_payload
)
assert exc_info.value.header["req_id"] == REQUEST_ID
assert exc_info.value.header["sink_id"] == SINK_ID_2
assert exc_info.value.header["time_ms_epoch"] == TEST_TIME
18 changes: 13 additions & 5 deletions wirepas_mesh_messaging/set_scratchpad_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
See file LICENSE for full license details.
"""

from wirepas_mesh_messaging.wirepas_exceptions import InvalidMessageContents
from .proto import GenericMessage

from .request import Request
Expand Down Expand Up @@ -86,15 +87,22 @@ def _get_related_message(generic_message):
def from_payload(cls, payload):
req = cls._decode_and_get_related_message(payload)

d = Request._parse_request_header(req.header)
header = Request._parse_request_header(req.header)

target = {}
parse_scratchpad_target(req.target_and_action, target)

return cls(sink_id=d["sink_id"],
target=target,
req_id=d["req_id"],
time_ms_epoch=d["time_ms_epoch"])
try:
return cls(
sink_id=header["sink_id"],
target=target,
req_id=header["req_id"],
time_ms_epoch=header["time_ms_epoch"],
)
except ValueError as e:
raise InvalidMessageContents(
f"Invalid values in {cls.__name__}", header
) from e

@property
def payload(self):
Expand Down
13 changes: 13 additions & 0 deletions wirepas_mesh_messaging/wirepas_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,16 @@ class InvalidMessageType(GatewayAPIParsingException):
"""
Exception indicating wrong message type during deserialization
"""

class InvalidMessageContents(GatewayAPIParsingException):
"""
Exception indicating invalid message contents in the received message.
Parameters:
- message: The exception message
- header: Parsed header of the message, as a dictionary
"""

def __init__(self, message, header):
super().__init__(message)
self.header = header

0 comments on commit 400b1e8

Please sign in to comment.