def test_clean_session_SUB_PUB__2_UNCLEAN_UNCLEAN__client_reSUBPUBs_and_sends_new_SUB_PUB( xift): ''' see xi_ftest_clean_session_helpers.py for the matrix codes below ''' clean_session_flag_queue = [0, 0] client_on_connect_action_queue = [22, 22] broker_on_message_action_queue = [2, 1, 1] client_on_publish_finish_action_queue = [0, 1] broker_on_subscribe_action_queue = [1, 0, 1, 1, 1] client_on_subscribe_finish_action_queue = [0, 0] helpers.generator_test_case_setup(xift, clean_session_flag_queue, client_on_connect_action_queue, broker_on_message_action_queue, client_on_publish_finish_action_queue, broker_on_subscribe_action_queue, client_on_subscribe_finish_action_queue) # Act act(xift) # Assert expected_calls_broker = [ call.broker.on_client_connect(ANY, ANY), call.broker.on_client_subscribe(ANY, ANY, ANY, 0), call.broker.on_client_subscribe(ANY, ANY, [(TestEssentials.topic_as_bytes, 0)], 0), call.broker.on_message( ANY, ANY, BasicMessageMatcher(TestEssentials.topic, 1, b'tm0')), call.broker.on_client_disconnect(ANY, ANY, ANY), call.broker.on_client_connect(ANY, ANY), call.broker.on_client_subscribe(ANY, ANY, ANY, 0), call.broker.on_client_subscribe(ANY, ANY, [(TestEssentials.topic_as_bytes, 0)], 1), call.broker.on_message( ANY, ANY, BasicMessageMatcher(TestEssentials.topic, 1, b'tm0', 1)), call.broker.on_client_subscribe(ANY, ANY, [(TestEssentials.topic_as_bytes, 0)], 0), call.broker.on_message( ANY, ANY, BasicMessageMatcher(TestEssentials.topic, 1, b'tm1', 0)), call.broker.on_client_disconnect(ANY, ANY, ANY) ] expected_calls_client = [ call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_disconnect(XiClientErrorCodes.SUCCESS), call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_subscribe_finish([XiClientErrorCodes.SUCCESS]), call.client.on_publish_finish(ANY), call.client.on_subscribe_finish([XiClientErrorCodes.SUCCESS]), call.client.on_publish_finish(ANY), call.client.on_disconnect(XiClientErrorCodes.SUCCESS) ] assert expected_calls_broker == xift.mock_call_history_broker.method_calls assert expected_calls_client == xift.mock_call_history_client.method_calls
def test_clean_session_PUB__2_CLEAN_CLEAN__NO_redelivery(xift): ''' see xi_ftest_clean_session_helpers.py for the matrix codes below ''' clean_session_flag_queue = [1, 1] client_on_connect_action_queue = [1, 9] broker_on_message_action_queue = [2, 1] helpers.generator_test_case_setup(xift, clean_session_flag_queue, client_on_connect_action_queue, broker_on_message_action_queue) # Act act(xift) # Assert expected_calls_broker = [ call.broker.on_client_connect(ANY, ANY), call.broker.on_client_subscribe(ANY, ANY, ANY, 0), call.broker.on_message( ANY, ANY, BasicMessageMatcher(TestEssentials.topic, 1, b'tm0')), call.broker.on_client_disconnect(ANY, ANY, ANY), call.broker.on_client_connect(ANY, ANY), call.broker.on_client_subscribe(ANY, ANY, ANY, 0), call.broker.on_client_disconnect(ANY, ANY, ANY) ] expected_calls_client = [ call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_disconnect(XiClientErrorCodes.SUCCESS), call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_disconnect(XiClientErrorCodes.SUCCESS) ] assert expected_calls_broker == xift.mock_call_history_broker.method_calls assert expected_calls_client == xift.mock_call_history_client.method_calls
def test_clean_session_PUB__2_UNCLEAN_UNCLEAN__client_redelivers_PUBLISH(xift): clean_session_flag_queue = [0, 0] client_on_connect_action_queue = [1, 0] broker_on_message_action_queue = [2, 1] helpers.generator_test_case_setup(xift, clean_session_flag_queue, client_on_connect_action_queue, broker_on_message_action_queue) # Act act(xift) # Assert expected_calls_broker = [ call.broker.on_client_connect(ANY, ANY), call.broker.on_client_subscribe(ANY, ANY, ANY, 0), call.broker.on_message( ANY, ANY, BasicMessageMatcher(TestEssentials.topic, 1, b'tm0')), call.broker.on_client_disconnect(ANY, ANY, ANY), call.broker.on_client_connect(ANY, ANY), call.broker.on_client_subscribe(ANY, ANY, ANY, 0), call.broker.on_message( ANY, ANY, BasicMessageMatcher(TestEssentials.topic, 1, b'tm0', 1)), call.broker.on_client_disconnect(ANY, ANY, ANY) ] expected_calls_client = [ call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_disconnect(XiClientErrorCodes.SUCCESS), call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_publish_finish(ANY), call.client.on_disconnect(XiClientErrorCodes.SUCCESS) ] assert expected_calls_broker == xift.mock_call_history_broker.method_calls assert expected_calls_client == xift.mock_call_history_client.method_calls
def test_device_status_data_publish_on_boot(xift): if xift.sut_platform == XiClientPlatform.C: pytest.xfail("feature can be activated only for python clients") # Arrange xift.client_sut.on_connect_finish.side_effect = lambda connect_res: xift.client_sut.disconnect( ) xift.client_sut.on_disconnect.side_effect = lambda return_code: xift.client_sut.stop( ) xift.client_sut.on_publish_finish.side_effect = None xift.broker.on_client_connect.side_effect = lambda userdata, connect_options: \ xift.broker.send_connack(mqtt_messages.CONNACK_ACCEPTED) xift.broker.on_client_disconnect.side_effect = lambda br, userdata, rc: \ xift.broker.trigger_shutdown() xift.broker.on_client_subscribe.side_effect = lambda userdata, msg_id, topics_and_qos, dup: \ xift.broker.send_suback(msg_id, topics_and_qos) xift.broker.on_message.side_effect = None # no need to puback for now # Act act(xift) # Assert expected_calls_broker = [ call.broker.on_client_connect(ANY, ANY), call.broker.on_client_subscribe( ANY, ANY, [(TestEssentials.control_topic_name, 1)], 0), call.broker.on_message(ANY, ANY, BasicMessageMatcher("device-status", 0, None)), call.broker.on_client_disconnect(xift.broker, ANY, MQTT_ERR_SUCCESS) ] expected_calls_client = [ call.client.on_publish_finish(ANY), call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_disconnect(ANY) ] assert expected_calls_broker == xift.mock_call_history_broker.method_calls assert expected_calls_client == xift.mock_call_history_client.method_calls
def test_subscribe_subscribeIncomingPublishQoS0_subscribeClbCalledSuccess( xift): """ Tests the correct behaviour when client subscribes to a topic and an incoming message arrives on the topic. Test scenario: Client Attempts to Subscribe to a Topic, Server sends a message on topic after SUBACK Expectation: Client should invoke subscription callback """ ### # broker flow # 1. accept connection, send connack # 2. accept the control topic topic subscription # 3. accept the standard topic subscription, check for QoS 0 # 4. Cleanup on Disconnect broker_flow = [ call.broker.on_client_connect(ANY, ANY), call.broker.on_client_subscribe(ANY, ANY, ANY, 0), # 3. check for QoS 0 call.broker.on_client_subscribe( ANY, ANY, [(TestEssentials.topic_as_signed_chars, 0)], 0), call.broker.on_client_disconnect(xift.broker, ANY, MQTT_ERR_SUCCESS) ] # 1. accept connection, send connack xift.broker.on_client_connect.side_effect = lambda userdata, connect_options: \ xift.broker.send_connack(mqtt_messages.CONNACK_ACCEPTED) # 2. accept the control topic topic subscription # 3. accept the standard topic subscription, xift.broker.on_client_subscribe.side_effect = lambda userdata, msg_id, topics_and_qos, dup: \ xift.broker.send_suback( msg_id, topics_and_qos ) # 4. Cleanup on Disconnect xift.broker.on_client_disconnect.side_effect = lambda br, userdata, rc: \ xift.broker.trigger_shutdown() ### # client flow # 1. connect (automagically through act()) # 1a. hidden, subscribe to control topic. # 2. on connect response, subscribe to topic # 3. subscription callback invoked, broker to publish to topic client subscribed to. # 4. on message callback, validate message, shutdown connection # 5. on shutdown callback, stop. # Validates that the message parameters are what we expect to recieve on the client. client_flow = [ call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_subscribe_finish( [ANY]), # 3. subscription callback invoked call.client.on_message_received( ANY, # 4. on message callback validate message BasicMessageMatcher( TestEssentials.topic, 0, #qos_level TestEssentials.payload_as_bytes)), call.client.on_disconnect(ANY) ] # 2. on connect response, subscribe to topic xift.client_sut.on_connect_finish.side_effect = lambda connect_response: \ xift.client_sut.subscribe([[TestEssentials.topic, 0]]) # 3. subscription callback invoked, broker to publish to topic client subscribed to. xift.client_sut.on_subscribe_finish.side_effect = lambda granted_access_list: \ xift.broker.publish(TestEssentials.topic, TestEssentials.payload_as_string) # 4. on message callback, ..., shutdown connection xift.client_sut.on_message_received.side_effect = lambda topic, message: \ xift.client_sut.disconnect() # 5. on shutdown callback, stop. xift.client_sut.on_disconnect.side_effect = lambda return_code: xift.client_sut.stop( ) ### # Act act(xift) ### # Assert assert broker_flow == xift.mock_call_history_broker.method_calls assert client_flow == xift.mock_call_history_client.method_calls
def subscribeAtQoS_BrokerPublishMessageAtQoS_Runner(xift, subscribe_qos, publish_qos): """ Tests the correct behaviour when client subscribes to a topic at variable QoS levels and Broker Publishes to the topic at variable QoS levels. Test ensures that the various QoS levels reach the broker correctly and are correctly provided to the callbacks to the client application """ ### # broker flow # 1. accept connection, send connack # 2. accept the control topic topic subscription # 3. accept the standard topic subscription, check for 'subscribe_qos' # 4. Cleanup on Disconnect broker_flow = [ call.broker.on_client_connect(ANY, ANY), # 2. accept the control topic topic subscription call.broker.on_client_subscribe( ANY, ANY, [(TestEssentials.control_topic_name, 1)], 0), # 3. accept the standard topic subscription, check for 'subscribe_qos' call.broker.on_client_subscribe( ANY, ANY, [(TestEssentials.topic_as_signed_chars, subscribe_qos)], 0), call.broker.on_client_disconnect(xift.broker, ANY, MQTT_ERR_SUCCESS) ] # 1. accept connection, send connack xift.broker.on_client_connect.side_effect = lambda userdata, connect_options: \ xift.broker.send_connack(mqtt_messages.CONNACK_ACCEPTED) # 2. accept the control topic topic subscription # 3. accept the standard topic subscription xift.broker.on_client_subscribe.side_effect = lambda userdata, msg_id, topics_and_qos, dup: \ xift.broker.send_suback( msg_id, topics_and_qos ) # 4. Cleanup on Disconnect xift.broker.on_client_disconnect.side_effect = lambda br, userdata, rc: \ xift.broker.trigger_shutdown() ### # client flow # 1. connect (automagically through act()) # 1a. hidden, subscribe to control topic. # 2. on connect response, subscribe to topic # 3. subscription callback invoked, broker to publish to topic client subscribed to. # 4. on message callback, validate message, shutdown connection # 5. on shutdown callback, stop. # Validates that the message parameters are what we expect to recieve on the client. client_flow = [ call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_subscribe_finish([ANY]), # 4. on message callback, validate message, call.client.on_message_received( ANY, BasicMessageMatcher(TestEssentials.topic, publish_qos, TestEssentials.payload_as_bytes)), call.client.on_disconnect(ANY) ] #2. on connect response, subscribe to topic xift.client_sut.on_connect_finish.side_effect = lambda connect_res: \ xift.client_sut.subscribe([[TestEssentials.topic, subscribe_qos]]) # 3. subscription callback invoked, broker publish to topic client subscribed to. xift.client_sut.on_subscribe_finish.side_effect = lambda granted_access_list: \ xift.broker.publish( TestEssentials.topic, TestEssentials.payload_as_string, publish_qos ) # 4. on message callback, shutdown connection xift.client_sut.on_message_received.side_effect = lambda topic, message: \ xift.client_sut.disconnect() # 5. on shutdown callback, stop. xift.client_sut.on_disconnect.side_effect = lambda return_code: xift.client_sut.stop( ) ## #Act act(xift) ## #Assert assert client_flow == xift.mock_call_history_client.method_calls assert broker_flow == xift.mock_call_history_broker.method_calls
def standard_publish_flow(xift, topic, payload, expected_payload, is_string, qos_level): ### # broker flow # 1. accept connection, send connack # 2. accept the control topic topic subscription # 3. test to see if the message arrived properly formatted via Mesage Matcher # 4. send puback # 5. cleanup on client disconnect broker_flow = [ call.broker.on_client_connect(ANY, ANY), call.broker.on_client_subscribe( ANY, ANY, [(TestEssentials.control_topic_name, 1)], 0), call.broker.on_message( ANY, ANY, BasicMessageMatcher(topic, qos_level, expected_payload)), call.broker.on_client_disconnect(xift.broker, ANY, MQTT_ERR_SUCCESS) ] # 1. accept connection, send connack xift.broker.on_client_connect.side_effect = lambda userdata, connect_options: \ xift.broker.send_connack(mqtt_messages.CONNACK_ACCEPTED) # 2. accept the control topic topic subscription xift.broker.on_client_subscribe.side_effect = lambda userdata, msg_id, topics_and_qos, dup: \ xift.broker.send_suback( msg_id, topics_and_qos ) # 4. send puback if qos1 or above def broker_on_message(a, b, mqtt_message): if qos_level == 0: pass else: xift.broker.send_puback(mqtt_message.mid) xift.broker.on_message.side_effect = broker_on_message # 5. cleanup on client disconnect xift.broker.on_client_disconnect.side_effect = lambda br, userdata, rc: \ xift.broker.trigger_shutdown() ### # client flow # 1. connect (automagically through act()) # 1a. hidden, subscribe to control topic. # 2. on connect response, publish to topic # 3. publish complete callback is called, shutdown. # 4. on shutdown callback, stop. client_flow = [ call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_publish_finish(ANY), call.client.on_disconnect(ANY) ] def connect_finish(connect_response): if is_string == True: xift.client_sut.publish_string(topic, payload, qos_level) else: xift.client_sut.publish_binary(topic, payload, qos_level) # 2. on connect response, subscribe to topic xift.client_sut.on_connect_finish.side_effect = connect_finish # 3. publish complete callback is called, shutdown. xift.client_sut.on_publish_finish.side_effect = lambda return_code: \ xift.client_sut.disconnect() # 4. on shutdown callback, stop. xift.client_sut.on_disconnect.side_effect = lambda return_code: xift.client_sut.stop( ) ### # Act act(xift) ### # Assert assert broker_flow == xift.mock_call_history_broker.method_calls assert client_flow == xift.mock_call_history_client.method_calls
def publish_with_broker_disconnect_before_puback(xift, qos_level): ### # broker flow # 1. accept connection, send connack # 2. accept the control topic topic subscription # 3. reject publish on test topic broker_flow = [ call.broker.on_client_connect(ANY, ANY), call.broker.on_client_subscribe(ANY, ANY, ANY, 0), call.broker.on_message( ANY, ANY, BasicMessageMatcher(TestEssentials.topic, qos_level, TestEssentials.payload_as_bytes)) ] # 1. accept connection, send connack xift.broker.on_client_connect.side_effect = lambda userdata, connect_options: \ xift.broker.send_connack(mqtt_messages.CONNACK_ACCEPTED) # 2. accept the control topic topic subscription xift.broker.on_client_subscribe.side_effect = lambda userdata, msg_id, topics_and_qos, dup: \ xift.broker.send_suback( msg_id, topics_and_qos ) # 3. reject publish on test topic xift.broker.on_message.side_effect = lambda a, bb, mqtt_message: \ xift.broker.trigger_shutdown() ### # client flow # 1. connect (automagically through act()) # 1a. hidden, subscribe to control topic. # 2. on connect response, publish to topic # 3. on shutdown callback, stop. if qos_level == 0: client_flow = [ call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_publish_finish(ANY), call.client.on_disconnect(ANY) ] else: client_flow = [ call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_disconnect(ANY) ] # 2. on connect response, subscribe to topic xift.client_sut.on_connect_finish.side_effect = lambda connect_response: \ xift.client_sut.publish_string(TestEssentials.topic, TestEssentials.payload_as_string, qos_level ) xift.client_sut.on_publish_finish.side_effect = None # 3. on shutdown callback, stop. xift.client_sut.on_disconnect.side_effect = lambda return_code: \ xift.client_sut.stop() ### # Act act(xift) ### # Assert assert broker_flow == xift.mock_call_history_broker.method_calls assert client_flow == xift.mock_call_history_client.method_calls
def test_publish_PublishQoS1_DisconnectAfterPuback(xift): """ Tests the correct behaviour when client publishes to a topic and gets disconnected after QoS 1 Puback. Test scenario: Client Attempts to Publish to a Topic, Server disconnects after puback. Expectation: Xively Client should have its disconnected callback invoked """ ### # broker flow # 1. accept connection, send connack # 2. accept the control topic topic subscription # 3. send puback on message broker_flow = [ call.broker.on_client_connect(ANY, ANY), call.broker.on_client_subscribe(ANY, ANY, ANY, 0), call.broker.on_message( ANY, ANY, BasicMessageMatcher( TestEssentials.topic, 1, #qos_level TestEssentials.payload_as_bytes)) ] # 1. accept connection, send connack xift.broker.on_client_connect.side_effect = lambda userdata, connect_options: \ xift.broker.send_connack(mqtt_messages.CONNACK_ACCEPTED) # 2. accept the control topic topic subscription xift.broker.on_client_subscribe.side_effect = lambda userdata, msg_id, topics_and_qos, dup: \ xift.broker.send_suback( msg_id, topics_and_qos ) # 3. send puback on message xift.broker.on_message.side_effect = lambda a, b, mqtt_message: \ xift.broker.send_puback(mqtt_message.mid) ### # client flow # 1. connect (automagically through act()) # 1a. hidden, subscribe to control topic. # 2. on connect response, publish to topic # 3. on puback, have broker trigger shudown. # 3. on shutdown callback, stop. client_flow = [ call.client.on_connect_finish(mqtt_messages.CONNACK_ACCEPTED), call.client.on_publish_finish(ANY), call.client.on_disconnect(ANY) ] # 2. on connect response, subscribe to topic xift.client_sut.on_connect_finish.side_effect = lambda connect_response: \ xift.client_sut.publish_string(TestEssentials.topic, TestEssentials.payload_as_string, 1 ) xift.client_sut.on_publish_finish.side_effect = lambda return_code: \ xift.broker.trigger_shutdown() # 3. on shutdown callback, stop. xift.client_sut.on_disconnect.side_effect = lambda return_code: \ xift.client_sut.stop() ### # Act act(xift) ### # Assert assert broker_flow == xift.mock_call_history_broker.method_calls assert client_flow == xift.mock_call_history_client.method_calls