Example #1
0
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
Example #4
0
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