async def _mgmt_request_response( self, mgmt_operation, message, callback, keep_alive_associated_link=True, timeout=None, **kwargs ): # type: (bytes, uamqp.Message, Callable, bool, Optional[float], Any) -> uamqp.Message """ Execute an amqp management operation. :param bytes mgmt_operation: The type of operation to be performed. This value will be service-specific, but common values include READ, CREATE and UPDATE. This value will be added as an application property on the message. :param message: The message to send in the management request. :paramtype message: ~uamqp.message.Message :param callback: The callback which is used to parse the returning message. :paramtype callback: Callable[int, ~uamqp.message.Message, str] :param keep_alive_associated_link: A boolean flag for keeping associated amqp sender/receiver link alive when executing operation on mgmt links. :param timeout: timeout in seconds for executing the mgmt operation. :rtype: None """ await self._open() application_properties = {} # Some mgmt calls do not support an associated link name (such as list_sessions). Most do, so on by default. if keep_alive_associated_link: try: application_properties = { ASSOCIATEDLINKPROPERTYNAME: self._handler.message_handler.name } except AttributeError: pass mgmt_msg = uamqp.Message( body=message, properties=MessageProperties( reply_to=self._mgmt_target, encoding=self._config.encoding, **kwargs ), application_properties=application_properties, ) try: return await self._handler.mgmt_request_async( mgmt_msg, mgmt_operation, op_type=MGMT_REQUEST_OP_TYPE_ENTITY_MGMT, node=self._mgmt_target.encode(self._config.encoding), timeout=timeout * 1000 if timeout else None, callback=callback, ) except Exception as exp: # pylint: disable=broad-except if isinstance(exp, compat.TimeoutException): raise OperationTimeoutError(error=exp) raise
def test_parse_message_should_succeed( self, device_id, encoding, content_type, interface_name, payload, properties, app_properties, module_id, ): # setup properties = MessageProperties(content_encoding=encoding, content_type=content_type) message = Message( body=json.dumps(payload).encode(), properties=properties, annotations={ common_parser.DEVICE_ID_IDENTIFIER: device_id.encode(), common_parser.INTERFACE_NAME_IDENTIFIER: interface_name.encode(), common_parser.MODULE_ID_IDENTIFIER: module_id.encode(), }, application_properties=_encode_app_props(app_properties), ) args = CommonParserArguments(properties=["all"], content_type=content_type) parser = common_parser.CommonParser(message=message, common_parser_args=args) # act parsed_msg = parser.parse_message() # verify assert parsed_msg["event"]["payload"] == payload assert parsed_msg["event"]["origin"] == device_id device_identifier = str(common_parser.DEVICE_ID_IDENTIFIER, "utf8") assert parsed_msg["event"]["annotations"][ device_identifier] == device_id module_identifier = str(common_parser.MODULE_ID_IDENTIFIER, "utf8") if module_id: assert parsed_msg["event"]["annotations"][ module_identifier] == module_id else: assert not parsed_msg["event"]["annotations"].get( module_identifier) properties = parsed_msg["event"]["properties"] assert properties["system"]["content_encoding"] == encoding assert properties["system"]["content_type"] == content_type assert properties["application"] == app_properties assert len(parser.issues_handler.get_all_issues()) == 0
def test_validate_invalid_telmetry_component_template_should_fail(self): # setup device_template = Template( load_json(FileNames.central_property_validation_template_file)) properties = MessageProperties(content_encoding=self.encoding, content_type=self.content_type) message = Message( body=json.dumps(self.bad_dcm_payload).encode(), properties=properties, annotations={ common_parser.DEVICE_ID_IDENTIFIER: self.device_id.encode(), common_parser.COMPONENT_NAME_IDENTIFIER: list(device_template.components.keys())[1].encode(), }, application_properties=_encode_app_props(self.app_properties), ) args = CommonParserArguments(properties=["all"]) parser = self._create_parser(device_template=device_template, message=message, args=args) # act parsed_msg = parser.parse_message() # verify assert parsed_msg["event"]["payload"] == self.bad_dcm_payload assert parsed_msg["event"]["origin"] == self.device_id device_identifier = str(common_parser.DEVICE_ID_IDENTIFIER, "utf8") assert parsed_msg["event"]["annotations"][ device_identifier] == self.device_id component_identifier = str(common_parser.COMPONENT_NAME_IDENTIFIER, "utf8") assert ( parsed_msg["event"]["annotations"][component_identifier] == list( device_template.components.keys())[1]) properties = parsed_msg["event"]["properties"] assert properties["system"]["content_encoding"] == self.encoding assert properties["system"]["content_type"] == self.content_type assert properties["application"] == self.app_properties expected_details = strings.invalid_field_name_component_mismatch_template( list(self.bad_dcm_payload.keys()), device_template.component_schema_names, ) _validate_issues(parser, Severity.warning, 1, 1, [expected_details])
def xtest_validate_against_template_should_fail(self): # setup device_template = self._get_template() properties = MessageProperties(content_encoding=self.encoding, content_type=self.content_type) message = Message( body=json.dumps(self.bad_dcm_payload).encode(), properties=properties, annotations={ common_parser.DEVICE_ID_IDENTIFIER: self.device_id.encode() }, application_properties=_encode_app_props(self.app_properties), ) args = CommonParserArguments(properties=["all"]) parser = self._create_parser(device_template=device_template, message=message, args=args) # act parsed_msg = parser.parse_message() schema = parser._extract_template_schemas_from_template( device_template) schema = parser._extract_template_schemas_from_template( device_template) # verify assert parsed_msg["event"]["payload"] == self.bad_dcm_payload assert parsed_msg["event"]["origin"] == self.device_id device_identifier = str(common_parser.DEVICE_ID_IDENTIFIER, "utf8") assert parsed_msg["event"]["annotations"][ device_identifier] == self.device_id properties = parsed_msg["event"]["properties"] assert properties["system"]["content_encoding"] == self.encoding assert properties["system"]["content_type"] == self.content_type assert properties["application"] == self.app_properties expected_details = strings.invalid_field_name_mismatch_template( list(self.bad_dcm_payload.keys()), list(schema.keys())) _validate_issues(parser, Severity.warning, 1, 1, [expected_details])
def test_parse_message_should_succeed(self): # setup app_prop_type = "some_app_prop" app_prop_value = "some_app_value" properties = MessageProperties(content_encoding=self.encoding, content_type=self.content_type) message = Message( body=json.dumps(self.payload).encode(), properties=properties, annotations={ _parser.DEVICE_ID_IDENTIFIER: self.device_id.encode() }, application_properties={ app_prop_type.encode(): app_prop_value.encode() }, ) parser = _parser.Event3Parser() # act parsed_msg = parser.parse_message( message=message, pnp_context=False, interface_name=None, properties={"all"}, content_type_hint=None, simulate_errors=False, ) # verify assert parsed_msg["event"]["payload"] == self.payload assert parsed_msg["event"]["origin"] == self.device_id device_identifier = str(_parser.DEVICE_ID_IDENTIFIER, "utf8") assert parsed_msg["event"]["annotations"][ device_identifier] == self.device_id properties = parsed_msg["event"]["properties"] assert properties["system"]["content_encoding"] == self.encoding assert properties["system"]["content_type"] == self.content_type assert properties["application"][app_prop_type] == app_prop_value assert len(parser._errors) == 0 assert len(parser._warnings) == 0 assert len(parser._info) == 0
def test_parse_message_bad_encoding_should_warn(self): # setup properties = MessageProperties(content_encoding=self.bad_encoding, content_type=self.content_type) message = Message( body=json.dumps(self.payload).encode(self.bad_encoding), properties=properties, annotations={ common_parser.DEVICE_ID_IDENTIFIER: self.device_id.encode() }, ) args = CommonParserArguments() parser = common_parser.CommonParser(message=message, common_parser_args=args) # act parser.parse_message() expected_details = strings.invalid_encoding(self.bad_encoding) _validate_issues(parser, Severity.warning, 1, 1, [expected_details])
def _mgmt_request_response(self, operation, message, callback, **kwargs): if not self.running: raise InvalidHandlerState("Client connection is closed.") mgmt_msg = Message(body=message, properties=MessageProperties( reply_to=self.mgmt_target, encoding=self.encoding, **kwargs)) try: return self._handler.mgmt_request(mgmt_msg, operation, op_type=b"entity-mgmt", node=self.mgmt_target.encode( self.encoding), timeout=5000, callback=callback) except Exception as exp: # pylint: disable=broad-except raise ServiceBusError("Management request failed: {}".format(exp), exp)
def test_parse_message_pnp_should_fail(self): # setup actual_interface_name = "actual_interface_name" expected_interface_name = "expected_interface_name" properties = MessageProperties(content_encoding=self.encoding, content_type=self.content_type) message = Message( body=json.dumps(self.payload).encode(), properties=properties, annotations={ _parser.DEVICE_ID_IDENTIFIER: self.device_id.encode(), _parser.INTERFACE_NAME_IDENTIFIER: actual_interface_name.encode(), }, ) parser = _parser.Event3Parser() # act parsed_msg = parser.parse_message( message=message, pnp_context=True, interface_name=expected_interface_name, properties=None, content_type_hint=None, simulate_errors=False, ) # verify # all the items should still be parsed and available, but we should have an error assert parsed_msg["event"]["payload"] == self.payload assert parsed_msg["event"]["origin"] == self.device_id assert parsed_msg["event"]["interface"] == actual_interface_name assert len(parser._errors) == 1 assert len(parser._warnings) == 0 assert len(parser._info) == 0 actual_error = parser._errors[0] expected_error = "Inteface name mismatch. {}. Expected: {}, Actual: {}".format( self.device_id, expected_interface_name, actual_interface_name) assert actual_error == expected_error
async def _mgmt_request_response(self, mgmt_operation, message, callback, **kwargs): await self._open() if not self._running: raise InvalidHandlerState("Client connection is closed.") mgmt_msg = uamqp.Message( body=message, properties=MessageProperties( reply_to=self._mgmt_target, encoding=self._config.encoding, **kwargs)) try: return await self._handler.mgmt_request_async( mgmt_msg, mgmt_operation, op_type=MGMT_REQUEST_OP_TYPE_ENTITY_MGMT, node=self._mgmt_target.encode(self._config.encoding), timeout=5000, callback=callback) except Exception as exp: # pylint: disable=broad-except raise ServiceBusError("Management request failed: {}".format(exp), exp)
async def _mgmt_request_response(self, mgmt_operation, message, callback, keep_alive_associated_link=True, **kwargs): await self._open() if not self._running: raise InvalidHandlerState("Client connection is closed.") application_properties = {} # Some mgmt calls do not support an associated link name (such as list_sessions). Most do, so on by default. if keep_alive_associated_link: try: application_properties = { ASSOCIATEDLINKPROPERTYNAME: self._handler.message_handler.name } except AttributeError: pass mgmt_msg = uamqp.Message(body=message, properties=MessageProperties( reply_to=self._mgmt_target, encoding=self._config.encoding, **kwargs), application_properties=application_properties) try: return await self._handler.mgmt_request_async( mgmt_msg, mgmt_operation, op_type=MGMT_REQUEST_OP_TYPE_ENTITY_MGMT, node=self._mgmt_target.encode(self._config.encoding), timeout=5000, callback=callback) except Exception as exp: # pylint: disable=broad-except raise ServiceBusError("Management request failed: {}".format(exp), exp)
def __init__(self, body=None, batch=None, to_device=None, message=None): """ Initialize EventData. :param body: The data to send in a single message. :type body: str, bytes or list :param batch: A data generator to send batched messages. :type batch: Generator :param to_device: An IoT device to route to. :type to_device: str :param message: The received message. :type message: ~uamqp.message.Message """ self._partition_key = types.AMQPSymbol(EventData.PROP_PARTITION_KEY) self._annotations = {} self._app_properties = {} self.msg_properties = MessageProperties() if to_device: self.msg_properties.to = '/devices/{}/messages/devicebound'.format( to_device) if batch: self.message = BatchMessage(data=batch, multi_messages=True, properties=self.msg_properties) elif message: self.message = message self.msg_properties = message.properties self._annotations = message.annotations self._app_properties = message.application_properties else: if isinstance(body, list) and body: self.message = Message(body[0], properties=self.msg_properties) for more in body[1:]: self.message._body.append(more) # pylint: disable=protected-access elif body is None: raise ValueError("EventData cannot be None.") else: self.message = Message(body, properties=self.msg_properties)
def test_parse_message_bad_encoding_should_fail(self): # setup properties = MessageProperties(content_encoding=self.bad_encoding, content_type=self.content_type) message = Message( body=json.dumps(self.payload).encode(self.bad_encoding), properties=properties, annotations={ _parser.DEVICE_ID_IDENTIFIER: self.device_id.encode() }, ) parser = _parser.Event3Parser() # act parser.parse_message(message, None, None, None, None, False) assert len(parser._errors) == 1 assert len(parser._warnings) == 0 assert len(parser._info) == 0 errors = parser._errors[0] assert "Unsupported encoding detected: '{}'".format( self.bad_encoding) in errors
def _mgmt_request_response(self, operation, message, callback, keep_alive_associated_link=True, **kwargs): if not self.running: raise InvalidHandlerState("Client connection is closed.") application_properties = {} # Some mgmt calls do not support an associated link name. Most do, however, so on by default. if keep_alive_associated_link: try: application_properties = { ASSOCIATEDLINKPROPERTYNAME: self._handler.message_handler.name } except AttributeError: pass mgmt_msg = Message(body=message, properties=MessageProperties( reply_to=self.mgmt_target, encoding=self.encoding, **kwargs), application_properties=application_properties) try: return self._handler.mgmt_request(mgmt_msg, operation, op_type=b"entity-mgmt", node=self.mgmt_target.encode( self.encoding), timeout=5000, callback=callback) except Exception as exp: # pylint: disable=broad-except raise ServiceBusError("Management request failed: {}".format(exp), exp)
def test_parse_message_bad_json_should_fail(self): # setup properties = MessageProperties(content_encoding=self.encoding, content_type=self.content_type) message = Message( body=self.bad_payload.encode(), properties=properties, annotations={ common_parser.DEVICE_ID_IDENTIFIER: self.device_id.encode() }, ) args = CommonParserArguments() parser = common_parser.CommonParser(message=message, common_parser_args=args) # act parsed_msg = parser.parse_message() # verify # parsing should attempt to place raw payload into result even if parsing fails assert parsed_msg["event"]["payload"] == self.bad_payload expected_details = strings.invalid_json() _validate_issues(parser, Severity.error, 1, 1, [expected_details])
def __init__(self, body=None, to_device=None): """ Initialize EventData. :param body: The data to send in a single message. :type body: str, bytes or list :param to_device: An IoT device to route to. :type to_device: str """ self._annotations = {} self._app_properties = {} self._msg_properties = MessageProperties() if to_device: self._msg_properties.to = '/devices/{}/messages/devicebound'.format( to_device) if body and isinstance(body, list): self.message = Message(body[0], properties=self._msg_properties) for more in body[1:]: self.message._body.append(more) # pylint: disable=protected-access elif body is None: raise ValueError("EventData cannot be None.") else: self.message = Message(body, properties=self._msg_properties)
def test_message_pickle(): properties = MessageProperties() properties.message_id = '2' properties.user_id = '1' properties.to = 'dkfj' properties.subject = 'dsljv' properties.reply_to = "kdjfk" properties.correlation_id = 'ienag' properties.content_type = 'b' properties.content_encoding = '39ru' properties.absolute_expiry_time = 24 properties.creation_time = 10 properties.group_id = '3irow' properties.group_sequence = 39 properties.reply_to_group_id = '39rud' header = MessageHeader() header.delivery_count = 3 header.time_to_live = 5 header.first_acquirer = 'dkfj' header.durable = True header.priority = 4 data_message = Message(body=[b'testmessage1', b'testmessage2']) pickled = pickle.loads(pickle.dumps(data_message)) body = list(pickled.get_data()) assert len(body) == 2 assert body == [b'testmessage1', b'testmessage2'] sequence_message = Message(body=[[1234.56, b'testmessage2', True], [-1234.56, { b'key': b'value' }, False]], body_type=MessageBodyType.Sequence) pickled = pickle.loads(pickle.dumps(sequence_message)) body = list(pickled.get_data()) assert len(body) == 2 assert body == [[1234.56, b'testmessage2', True], [-1234.56, { b'key': b'value' }, False]] value_message = Message(body={b'key': [1, b'str', False]}, body_type=MessageBodyType.Value) pickled = pickle.loads(pickle.dumps(value_message)) body = pickled.get_data() assert body == {b'key': [1, b'str', False]} error = errors.MessageModified(False, False, {b'key': b'value'}) pickled_error = pickle.loads(pickle.dumps(error)) assert pickled_error._annotations == {b'key': b'value'} # pylint: disable=protected-access message = Message(body="test", properties=properties, header=header) message.on_send_complete = send_complete_callback message.footer = {'a': 2} message.state = constants.MessageState.ReceivedSettled pickled = pickle.loads(pickle.dumps(message)) assert list(message.get_data()) == [b"test"] assert message.footer == pickled.footer assert message.state == pickled.state assert message.application_properties == pickled.application_properties assert message.annotations == pickled.annotations assert message.delivery_annotations == pickled.delivery_annotations assert message.settled == pickled.settled assert message.properties.message_id == pickled.properties.message_id assert message.properties.user_id == pickled.properties.user_id assert message.properties.to == pickled.properties.to assert message.properties.subject == pickled.properties.subject assert message.properties.reply_to == pickled.properties.reply_to assert message.properties.correlation_id == pickled.properties.correlation_id assert message.properties.content_type == pickled.properties.content_type assert message.properties.content_encoding == pickled.properties.content_encoding assert message.properties.absolute_expiry_time == pickled.properties.absolute_expiry_time assert message.properties.creation_time == pickled.properties.creation_time assert message.properties.group_id == pickled.properties.group_id assert message.properties.group_sequence == pickled.properties.group_sequence assert message.properties.reply_to_group_id == pickled.properties.reply_to_group_id assert message.header.delivery_count == pickled.header.delivery_count assert message.header.time_to_live == pickled.header.time_to_live assert message.header.first_acquirer == pickled.header.first_acquirer assert message.header.durable == pickled.header.durable assert message.header.priority == pickled.header.priority # send with message param settler = errors.MessageAlreadySettled internal_message = c_uamqp.create_message() internal_message.add_body_data(b"hi") message_w_message_param = Message(message=internal_message, settler=settler, delivery_no=1) pickled = pickle.loads(pickle.dumps(message_w_message_param)) message_data = str(message_w_message_param.get_data()) pickled_data = str(pickled.get_data()) assert message_data == pickled_data assert message_w_message_param.footer == pickled.footer assert message_w_message_param.state == pickled.state assert message_w_message_param.application_properties == pickled.application_properties assert message_w_message_param.annotations == pickled.annotations assert message_w_message_param.delivery_annotations == pickled.delivery_annotations assert message_w_message_param.settled == pickled.settled assert pickled.delivery_no == 1 assert type(pickled._settler()) == type(settler()) # pylint: disable=protected-access
def test_message_properties(): properties = MessageProperties() assert properties.user_id is None properties = MessageProperties() properties.user_id = b'' assert properties.user_id == b'' properties = MessageProperties() properties.user_id = '1' assert properties.user_id == b'1' properties = MessageProperties() properties.user_id = 'short' assert properties.user_id == b'short' properties = MessageProperties() properties.user_id = 'longuseridstring' assert properties.user_id == b'longuseridstring' properties = MessageProperties() properties.user_id = '!@#$%^&*()_+1234567890' assert properties.user_id == b'!@#$%^&*()_+1234567890' properties = MessageProperties() properties.user_id = 'werid/0\0\1\t\n' assert properties.user_id == b'werid/0\0\1\t\n'
def test_deepcopy_batch_message(): ## DEEPCOPY WITH MESSAGES IN BATCH THAT HAVE HEADER/PROPERTIES properties = MessageProperties() properties.message_id = '2' properties.user_id = '1' properties.to = 'dkfj' properties.subject = 'dsljv' properties.reply_to = "kdjfk" properties.correlation_id = 'ienag' properties.content_type = 'b' properties.content_encoding = '39ru' properties.absolute_expiry_time = 24 properties.creation_time = 10 properties.group_id = '3irow' properties.group_sequence = 39 properties.reply_to_group_id = '39rud' header = MessageHeader() header.delivery_count = 3 header.time_to_live = 5 header.first_acquirer = 'dkfj' header.durable = True header.priority = 4 message = Message(body="test", properties=properties, header=header) message.on_send_complete = send_complete_callback message.footer = {'a': 2} message.state = constants.MessageState.ReceivedSettled message_batch = BatchMessage(data=[], multi_messages=False, properties=None) message_batch._body_gen.append(message) message_batch_copy = copy.deepcopy(message_batch) batch_message = list(message_batch._body_gen)[0] batch_copy_message = list(message_batch_copy._body_gen)[0] assert len(list(message_batch._body_gen)) == len( list(message_batch_copy._body_gen)) # check message attributes are equal to deepcopied message attributes assert list(batch_message.get_data()) == list( batch_copy_message.get_data()) assert batch_message.footer == batch_copy_message.footer assert batch_message.state == batch_copy_message.state assert batch_message.application_properties == batch_copy_message.application_properties assert batch_message.annotations == batch_copy_message.annotations assert batch_message.delivery_annotations == batch_copy_message.delivery_annotations assert batch_message.settled == batch_copy_message.settled assert batch_message.properties.message_id == batch_copy_message.properties.message_id assert batch_message.properties.user_id == batch_copy_message.properties.user_id assert batch_message.properties.to == batch_copy_message.properties.to assert batch_message.properties.subject == batch_copy_message.properties.subject assert batch_message.properties.reply_to == batch_copy_message.properties.reply_to assert batch_message.properties.correlation_id == batch_copy_message.properties.correlation_id assert batch_message.properties.content_type == batch_copy_message.properties.content_type assert batch_message.properties.content_encoding == batch_copy_message.properties.content_encoding assert batch_message.properties.absolute_expiry_time == batch_copy_message.properties.absolute_expiry_time assert batch_message.properties.creation_time == batch_copy_message.properties.creation_time assert batch_message.properties.group_id == batch_copy_message.properties.group_id assert batch_message.properties.group_sequence == batch_copy_message.properties.group_sequence assert batch_message.properties.reply_to_group_id == batch_copy_message.properties.reply_to_group_id assert batch_message.header.delivery_count == batch_copy_message.header.delivery_count assert batch_message.header.time_to_live == batch_copy_message.header.time_to_live assert batch_message.header.first_acquirer == batch_copy_message.header.first_acquirer assert batch_message.header.durable == batch_copy_message.header.durable assert batch_message.header.priority == batch_copy_message.header.priority