def test_route_method_request_will_route_method_to_generic_method_request_inbox_until_named_method_inbox_is_created( self, manager): # Two MethodRequests for the SAME method name method_name = "some_method" method_request1 = MethodRequest(request_id="1", name=method_name, payload="{'key': 'value'}") method_request2 = MethodRequest(request_id="2", name=method_name, payload="{'key': 'value'}") # Do NOT get a specific named inbox - just the generic one generic_method_inbox = manager.get_method_request_inbox() assert generic_method_inbox.empty() # Route the first method request delivered_request1 = manager.route_method_request(method_request1) assert delivered_request1 # Method Request 1 was delivered to the generic method inbox since the method name was unknown assert method_request1 in generic_method_inbox # Get an inbox for the specific method name named_method_inbox = manager.get_method_request_inbox(method_name) assert named_method_inbox.empty() # Route the second method request delivered_request2 = manager.route_method_request(method_request2) assert delivered_request2 # Method Request 2 was delivered to its corresponding named inbox since the method name is known assert method_request2 in named_method_inbox assert method_request2 not in generic_method_inbox
def test_payload_property_is_read_only(self): m_req = MethodRequest(request_id=dummy_rid, name=dummy_name, payload=dummy_payload) new_payload = {"NewPayload": "somenewpayload"} with pytest.raises(AttributeError): m_req.payload = new_payload assert m_req.payload != new_payload assert m_req.payload == dummy_payload
def test_request_id_property_is_read_only(self): m_req = MethodRequest(request_id=dummy_rid, name=dummy_name, payload=dummy_payload) new_rid = 2 with pytest.raises(AttributeError): m_req.request_id = new_rid assert m_req.request_id != new_rid assert m_req.request_id == dummy_rid
def test_name_property_is_read_only(self): m_req = MethodRequest(request_id=dummy_rid, name=dummy_name, payload=dummy_payload) new_name = "new_name" with pytest.raises(AttributeError): m_req.name = new_name assert m_req.name != new_name assert m_req.name == dummy_name
def test_clear_all_method_requests_clears_named_method_request_inboxes(self, manager): method_request_inbox1 = manager.get_method_request_inbox("some_method") method_request_inbox2 = manager.get_method_request_inbox("some_other_method") assert method_request_inbox1.empty() assert method_request_inbox2.empty() manager.route_method_request(MethodRequest("id1", "some_method", "payload")) manager.route_method_request(MethodRequest("id2", "some_other_method", "payload")) assert not method_request_inbox1.empty() assert not method_request_inbox2.empty() manager.clear_all_method_requests() assert method_request_inbox1.empty() assert method_request_inbox2.empty()
def test_clears_generic_method_request_inbox(self, manager): generic_method_request_inbox = manager.get_method_request_inbox() assert generic_method_request_inbox.empty() manager.route_method_request(MethodRequest("id", "unrecognized_method_name", "payload")) assert not generic_method_request_inbox.empty() manager.clear_all_method_requests() assert generic_method_request_inbox.empty()
def _handle_pipeline_event(self, event): """ Pipeline Event handler function to convert incoming MQTT messages into the appropriate IoTHub events, based on the topic of the message """ # TODO: should we always be decoding the payload? Seems strange to only sometimes do it. # Is there value to the user getting the original bytestring from the wire? if isinstance(event, pipeline_events_mqtt.IncomingMQTTMessageEvent): topic = event.topic device_id = self.nucleus.pipeline_configuration.device_id module_id = self.nucleus.pipeline_configuration.module_id if mqtt_topic_iothub.is_c2d_topic(topic, device_id): message = Message(event.payload) mqtt_topic_iothub.extract_message_properties_from_topic(topic, message) self.send_event_up(pipeline_events_iothub.C2DMessageEvent(message)) elif mqtt_topic_iothub.is_input_topic(topic, device_id, module_id): message = Message(event.payload) mqtt_topic_iothub.extract_message_properties_from_topic(topic, message) message.input_name = mqtt_topic_iothub.get_input_name_from_topic(topic) self.send_event_up(pipeline_events_iothub.InputMessageEvent(message)) elif mqtt_topic_iothub.is_method_topic(topic): request_id = mqtt_topic_iothub.get_method_request_id_from_topic(topic) method_name = mqtt_topic_iothub.get_method_name_from_topic(topic) method_received = MethodRequest( request_id=request_id, name=method_name, payload=json.loads(event.payload.decode("utf-8")), ) self.send_event_up(pipeline_events_iothub.MethodRequestEvent(method_received)) elif mqtt_topic_iothub.is_twin_response_topic(topic): request_id = mqtt_topic_iothub.get_twin_request_id_from_topic(topic) status_code = int(mqtt_topic_iothub.get_twin_status_code_from_topic(topic)) self.send_event_up( pipeline_events_base.ResponseEvent( request_id=request_id, status_code=status_code, response_body=event.payload ) ) elif mqtt_topic_iothub.is_twin_desired_property_patch_topic(topic): self.send_event_up( pipeline_events_iothub.TwinDesiredPropertiesPatchEvent( patch=json.loads(event.payload.decode("utf-8")) ) ) else: logger.debug("Unknown topic: {} passing up to next handler".format(topic)) self.send_event_up(event) else: # all other messages get passed up self.send_event_up(event)
def test_instantiates_without_payload(self): request = MethodRequest(request_id=dummy_rid, name=dummy_name, payload=dummy_payload) status = 200 response = MethodResponse.create_from_method_request(request, status) assert isinstance(response, MethodResponse) assert response.request_id == request.request_id assert response.status == status assert response.payload is None
def _handle_pipeline_event(self, event): """ Pipeline Event handler function to convert incoming MQTT messages into the appropriate IoTHub events, based on the topic of the message """ if isinstance(event, pipeline_events_mqtt.IncomingMQTTMessageEvent): topic = event.topic if mqtt_topic_iothub.is_c2d_topic(topic, self.device_id): message = Message(event.payload) mqtt_topic_iothub.extract_properties_from_topic(topic, message) self.send_event_up(pipeline_events_iothub.C2DMessageEvent(message)) elif mqtt_topic_iothub.is_input_topic(topic, self.device_id, self.module_id): message = Message(event.payload) mqtt_topic_iothub.extract_properties_from_topic(topic, message) input_name = mqtt_topic_iothub.get_input_name_from_topic(topic) self.send_event_up(pipeline_events_iothub.InputMessageEvent(input_name, message)) elif mqtt_topic_iothub.is_method_topic(topic): request_id = mqtt_topic_iothub.get_method_request_id_from_topic(topic) method_name = mqtt_topic_iothub.get_method_name_from_topic(topic) method_received = MethodRequest( request_id=request_id, name=method_name, payload=json.loads(event.payload.decode("utf-8")), ) self.send_event_up(pipeline_events_iothub.MethodRequestEvent(method_received)) elif mqtt_topic_iothub.is_twin_response_topic(topic): request_id = mqtt_topic_iothub.get_twin_request_id_from_topic(topic) status_code = int(mqtt_topic_iothub.get_twin_status_code_from_topic(topic)) self.send_event_up( pipeline_events_base.ResponseEvent( request_id=request_id, status_code=status_code, response_body=event.payload ) ) elif mqtt_topic_iothub.is_twin_desired_property_patch_topic(topic): self.send_event_up( pipeline_events_iothub.TwinDesiredPropertiesPatchEvent( patch=json.loads(event.payload.decode("utf-8")) ) ) else: logger.debug("Unknown topic: {} passing up to next handler".format(topic)) self.send_event_up(event) else: # all other messages get passed up super(IoTHubMQTTTranslationStage, self)._handle_pipeline_event(event)
def test_instantiates_from_method_request(self): request = MethodRequest(request_id=dummy_rid, name=dummy_name, payload=dummy_payload) status = 200 payload = {"ResponsePayload": "SomeResponse"} response = MethodResponse.create_from_method_request( method_request=request, status=status, payload=payload) assert isinstance(response, MethodResponse) assert response.request_id == request.request_id assert response.status == status assert response.payload == payload
def test_receive_method_request_called_without_method_name_returns_method_request_from_generic_method_inbox( self, mocker, client): request = MethodRequest(request_id="1", name="some_method", payload={"key": "value"}) inbox_mock = mocker.MagicMock(autospec=SyncClientInbox) inbox_mock.get.return_value = request manager_get_inbox_mock = mocker.patch.object( target=client._inbox_manager, attribute="get_method_request_inbox", return_value=inbox_mock, ) received_request = client.receive_method_request() assert manager_get_inbox_mock.call_count == 1 assert manager_get_inbox_mock.call_args == mocker.call(None) assert inbox_mock.get.call_count == 1 assert received_request is received_request
async def test_receive_method_request_called_with_method_name_returns_method_request_from_named_method_inbox( self, mocker, client): method_name = "some_method" request = MethodRequest(request_id="1", name=method_name, payload={"key": "value"}) inbox_mock = mocker.MagicMock(autospec=AsyncClientInbox) inbox_mock.get.return_value = await create_completed_future(request) manager_get_inbox_mock = mocker.patch.object( target=client._inbox_manager, attribute="get_method_request_inbox", return_value=inbox_mock, ) received_request = await client.receive_method_request(method_name) assert manager_get_inbox_mock.call_count == 1 assert manager_get_inbox_mock.call_args == mocker.call(method_name) assert inbox_mock.get.call_count == 1 assert received_request is received_request
def _handle_pipeline_event(self, event): """ Pipeline Event handler function to convert incoming Mqtt messages into the appropriate IotHub events, based on the topic of the message """ if isinstance(event, pipeline_events_mqtt.IncomingMessage): topic = event.topic if mqtt_topic.is_c2d_topic(topic): message = Message(event.payload) mqtt_topic.extract_properties_from_topic(topic, message) self.handle_pipeline_event( pipeline_events_iothub.C2DMessageEvent(message)) elif mqtt_topic.is_input_topic(topic): message = Message(event.payload) mqtt_topic.extract_properties_from_topic(topic, message) input_name = mqtt_topic.get_input_name_from_topic(topic) self.handle_pipeline_event( pipeline_events_iothub.InputMessageEvent( input_name, message)) elif mqtt_topic.is_method_topic(topic): rid = mqtt_topic.get_method_request_id_from_topic(topic) method_name = mqtt_topic.get_method_name_from_topic(topic) method_received = MethodRequest(request_id=rid, name=method_name, payload=json.loads( event.payload)) self._handle_pipeline_event( pipeline_events_iothub.MethodRequest(method_received)) else: logger.warning( "Warning: dropping message with topic {}".format(topic)) else: # all other messages get passed up PipelineStage._handle_pipeline_event(self, event)
def method_request(): return MethodRequest(request_id="1", name="some_method", payload={"key": "value"})
def method_request(self): return MethodRequest(request_id="1", name="some_method", payload="{'key': 'value'}")