Beispiel #1
0
    async def test_handle_pnp_commmand(
        self,
        client,
        event_loop,
        pnp_command_name,
        pnp_component_name,
        pnp_command_response_status,
        include_component_name,
        include_request_payload,
        include_response_payload,
        service_helper,
        device_id,
        module_id,
    ):
        actual_request = None

        if include_request_payload:
            request_payload = get_random_dict()
        else:
            request_payload = ""

        if include_response_payload:
            response_payload = get_random_dict()
        else:
            response_payload = None

        async def handle_on_command_request_received(request):
            nonlocal actual_request
            logger.info(
                "command request for component {}, command {} received".format(
                    request.component_name, request.command_name))
            actual_request = request
            logger.info("Sending response")
            await client.send_command_response(
                CommandResponse.create_from_command_request(
                    request, pnp_command_response_status, response_payload))

        client.on_command_request_received = handle_on_command_request_received
        await asyncio.sleep(1)  # wait for subscribe, etc, to complete

        # invoke the command
        command_response = await service_helper.invoke_pnp_command(
            device_id, module_id, pnp_component_name, pnp_command_name,
            request_payload)

        # verify that the method request arrived correctly
        assert actual_request.command_name == pnp_command_name
        assert actual_request.component_name == pnp_component_name

        if request_payload:
            assert actual_request.payload == request_payload
        else:
            assert not actual_request.payload

        # and make sure the response came back successfully
        # Currently no way to check the command response status code because the DigitalTwinClient A
        # object in the service SDK does not return this to the caller.
        # assert command_response[Fields.COMMAND_RESPONSE_STATUS_CODE] == command_response_status
        assert command_response == response_payload
    async def test_handle_method_call(
        self,
        client,
        method_name,
        method_response_status,
        include_request_payload,
        include_response_payload,
        service_helper,
        leak_tracker,
    ):
        leak_tracker.set_initial_object_list()

        actual_request = None

        if include_request_payload:
            request_payload = get_random_dict()
        else:
            request_payload = None

        if include_response_payload:
            response_payload = get_random_dict()
        else:
            response_payload = None

        async def handle_on_method_request_received(request):
            nonlocal actual_request
            logger.info("Method request for {} received".format(request.name))
            actual_request = request
            logger.info("Sending response")
            await client.send_method_response(
                MethodResponse.create_from_method_request(
                    request, method_response_status, response_payload))

        client.on_method_request_received = handle_on_method_request_received
        await asyncio.sleep(1)  # wait for subscribe, etc, to complete

        # invoke the method call
        method_response = await service_helper.invoke_method(
            method_name, request_payload)

        # verify that the method request arrived correctly
        assert actual_request.name == method_name
        if request_payload:
            assert actual_request.payload == request_payload
        else:
            assert not actual_request.payload

        # and make sure the response came back successfully
        assert method_response.status == method_response_status
        assert method_response.payload == response_payload

        actual_request = None  # so this isn't tagged as a leak
        leak_tracker.check_for_leaks()
Beispiel #3
0
    def test_handle_method_call(
        self,
        client,
        method_name,
        device_id,
        module_id,
        method_response_status,
        include_request_payload,
        include_response_payload,
        service_helper,
    ):

        if include_request_payload:
            request_payload = get_random_dict()
        else:
            request_payload = None

        if include_response_payload:
            response_payload = get_random_dict()
        else:
            response_payload = None

        # hack needed because there is no `nonlocal` keyword in py27.
        nonlocal_py27_hack = {"actual_request": None}

        def handle_on_method_request_received(request):
            logger.info("Method request for {} received".format(request.name))
            nonlocal_py27_hack["actual_request"] = request
            logger.info("Sending response")
            client.send_method_response(
                MethodResponse.create_from_method_request(
                    request, method_response_status, response_payload))

        client.on_method_request_received = handle_on_method_request_received
        time.sleep(1)  # wait for subscribe, etc, to complete

        # invoke the method call
        method_response = service_helper.invoke_method(device_id, module_id,
                                                       method_name,
                                                       request_payload)

        # verify that the method request arrived correctly
        actual_request = nonlocal_py27_hack["actual_request"]
        assert actual_request.name == method_name
        if request_payload:
            assert actual_request.payload == request_payload
        else:
            assert not actual_request.payload

        # and make sure the response came back successfully
        assert method_response.status == method_response_status
        assert method_response.payload == response_payload
Beispiel #4
0
    async def test_get_reported_property(
        self,
        client,
        pnp_read_only_property_name,
        pnp_component_name,
        is_component_property,
    ):
        random_property_value = get_random_dict()
        assert client.connected

        patch = ClientPropertyCollection()
        if is_component_property:
            patch.set_component_property(pnp_component_name,
                                         pnp_read_only_property_name,
                                         random_property_value)
        else:
            patch.set_property(pnp_read_only_property_name,
                               random_property_value)

        logger.info("Setting {} to {}".format(pnp_read_only_property_name,
                                              random_property_value))
        await client.update_client_properties(patch)

        properties = await client.get_client_properties()

        if is_component_property:
            assert (properties.reported_from_device.get_component_property(
                pnp_component_name,
                pnp_read_only_property_name) == random_property_value)

            assert properties.reported_from_device.backing_object[
                pnp_component_name]["__t"] == "c"
        else:
            assert (properties.reported_from_device.get_property(
                pnp_read_only_property_name) == random_property_value)
    async def test_receives_simple_desired_patch(self, client, event_loop,
                                                 service_helper, leak_tracker):
        leak_tracker.set_initial_object_list()

        received_patch = None
        received = asyncio.Event()

        async def handle_on_patch_received(patch):
            nonlocal received_patch, received
            print("received {}".format(patch))
            received_patch = patch
            event_loop.call_soon_threadsafe(received.set)

        client.on_twin_desired_properties_patch_received = handle_on_patch_received

        random_dict = get_random_dict()
        await service_helper.set_desired_properties(
            {const.TEST_CONTENT: random_dict}, )

        await asyncio.wait_for(received.wait(), 60)
        assert received.is_set()

        assert received_patch[const.TEST_CONTENT] == random_dict

        twin = await client.get_twin()
        assert twin[const.DESIRED][const.TEST_CONTENT] == random_dict
Beispiel #6
0
    def test_simple_patch(self, client, service_helper, device_id, module_id):

        received = threading.Event()

        # hack needed because there is no `nonlocal` keyword in py27.
        nonlocal_py27_hack = {"received_patch": None, "received": received}

        def handle_on_patch_received(patch):
            print("received {}".format(patch))
            nonlocal_py27_hack["received_patch"] = patch
            nonlocal_py27_hack["received"].set()

        client.on_twin_desired_properties_patch_received = handle_on_patch_received

        random_dict = get_random_dict()
        service_helper.set_desired_properties(
            device_id,
            module_id,
            {const.TEST_CONTENT: random_dict},
        )

        received.wait(timeout=10)
        logger.info("got it")

        assert nonlocal_py27_hack["received_patch"][
            const.TEST_CONTENT] == random_dict

        twin = client.get_twin()
        assert twin[const.DESIRED][const.TEST_CONTENT] == random_dict
    def test_sync_receives_simple_desired_patch(self, client, service_helper,
                                                leak_tracker):
        received_patches = queue.Queue()
        leak_tracker.set_initial_object_list()

        def handle_on_patch_received(patch):
            nonlocal received_patches
            print("received {}".format(patch))
            received_patches.put(patch)

        client.on_twin_desired_properties_patch_received = handle_on_patch_received

        # erase all old desired properties. Otherwise our random dict will only
        # be part of the twin we get when we call `get_twin` below (because of
        # properties from previous tests).
        service_helper.set_desired_properties({const.TEST_CONTENT: None}, )

        random_dict = get_random_dict()
        service_helper.set_desired_properties(
            {const.TEST_CONTENT: random_dict}, )

        while True:
            received_patch = received_patches.get(timeout=60)

            if received_patch[const.TEST_CONTENT] == random_dict:
                twin = client.get_twin()
                assert twin[const.DESIRED][const.TEST_CONTENT] == random_dict
                break

        leak_tracker.check_for_leaks()
Beispiel #8
0
    async def test_simple_patch(self, client, event_loop, service_helper,
                                device_id, module_id):

        received_patch = None
        received = asyncio.Event()

        async def handle_on_patch_received(patch):
            nonlocal received_patch, received
            print("received {}".format(patch))
            received_patch = patch
            event_loop.call_soon_threadsafe(received.set)

        client.on_twin_desired_properties_patch_received = handle_on_patch_received

        random_dict = get_random_dict()
        await service_helper.set_desired_properties(
            device_id,
            module_id,
            {const.TEST_CONTENT: random_dict},
        )

        await asyncio.wait_for(received.wait(), 10)
        logger.info("got it")

        assert received_patch[const.TEST_CONTENT] == random_dict

        twin = await client.get_twin()
        assert twin[const.DESIRED][const.TEST_CONTENT] == random_dict
    async def test_receive_c2d(self, client, service_helper, event_loop,
                               leak_tracker):
        leak_tracker.set_initial_object_list()

        message = json.dumps(get_random_dict())

        received_message = None
        received = asyncio.Event()

        async def handle_on_message_received(message):
            nonlocal received_message, received
            logger.info("received {}".format(message))
            received_message = message
            event_loop.call_soon_threadsafe(received.set)

        client.on_message_received = handle_on_message_received

        await service_helper.send_c2d(message, {})

        await asyncio.wait_for(received.wait(), 60)
        assert received.is_set()

        assert received_message.data.decode("utf-8") == message

        received_message = None  # so this isn't tagged as a leak
        leak_tracker.check_for_leaks()
    def test_sync_receive_c2d(self, client, service_helper, leak_tracker):
        leak_tracker.set_initial_object_list()

        message = json.dumps(get_random_dict())

        received_message = None
        received = threading.Event()

        def handle_on_message_received(message):
            nonlocal received_message, received
            logger.info("received {}".format(message))
            received_message = message
            received.set()

        client.on_message_received = handle_on_message_received

        service_helper.send_c2d(message, {})

        received.wait(timeout=60)
        assert received.is_set()

        assert received_message.data.decode("utf-8") == message

        received_message = None  # so this isn't tagged as a leak
        leak_tracker.check_for_leaks()
    def test_sync_sends_json_string(self, client, service_helper, leak_tracker):
        leak_tracker.set_initial_object_list()

        message = json.dumps(utils.get_random_dict())

        client.send_message(message)

        event = service_helper.wait_for_eventhub_arrival(None)
        assert json.dumps(event.message_body) == message

        leak_tracker.check_for_leaks()
Beispiel #12
0
    async def test_set_reported_property(
        self,
        client,
        pnp_read_only_property_name,
        pnp_component_name,
        is_component_property,
        service_helper,
        device_id,
        module_id,
    ):
        random_property_value = get_random_dict()
        assert client.connected

        patch = ClientPropertyCollection()
        if is_component_property:
            patch.set_component_property(pnp_component_name,
                                         pnp_read_only_property_name,
                                         random_property_value)
        else:
            patch.set_property(pnp_read_only_property_name,
                               random_property_value)

        logger.info("Setting {} to {}".format(pnp_read_only_property_name,
                                              random_property_value))
        await client.update_client_properties(patch)

        while True:
            properties = await service_helper.get_pnp_properties(
                device_id, module_id)

            if is_component_property:
                actual_value = properties.get(pnp_component_name, {}).get(
                    pnp_read_only_property_name, None)
            else:
                actual_value = properties.get(pnp_read_only_property_name,
                                              None)

            if actual_value == random_property_value:
                return

            else:
                logger.warning(
                    "property not matched yet.  Expected = {}, actual = {}".
                    format(random_property_value, actual_value))

            logger.warning(
                "digital_twin_client.get_digital_twin returned {}".format(
                    pprint.pformat(properties)))

            await asyncio.sleep(5)
Beispiel #13
0
    async def test_desired_properties_via_get_client_properties(
        self,
        event_loop,
        client,
        pnp_component_name,
        pnp_writable_property_name,
        is_component_property,
        service_helper,
        device_id,
        module_id,
    ):
        random_property_value = get_random_dict()
        received = asyncio.Event()

        async def handle_on_patch_received(patch):
            nonlocal received
            logger.info("received {}".format(patch))
            event_loop.call_soon_threadsafe(received.set)

        client.on_writable_property_update_request_received = handle_on_patch_received
        await asyncio.sleep(1)

        props = make_pnp_desired_property_patch(
            pnp_component_name if is_component_property else None,
            pnp_writable_property_name,
            random_property_value,
        )
        await service_helper.update_pnp_properties(device_id, module_id, props)

        # wait for the desired property patch to arrive at the client
        # We don't actually check the contents of the patch, but the
        # fact that it arrived means the device registry should have
        # finished ingesting the patch
        await asyncio.wait_for(received.wait(), 10)
        logger.info("got it")

        properties = await client.get_client_properties()
        if is_component_property:
            assert (
                properties.writable_properties_requests.get_component_property(
                    pnp_component_name,
                    pnp_writable_property_name) == random_property_value)
            assert (properties.writable_properties_requests.
                    backing_object[pnp_component_name]["__t"] == "c")
        else:
            assert (properties.writable_properties_requests.get_property(
                pnp_writable_property_name) == random_property_value)
Beispiel #14
0
    async def test_send_pnp_telemetry(self, client, pnp_model_id,
                                      get_next_eventhub_arrival):
        telemetry = get_random_dict()

        await client.send_telemetry(telemetry)
        event = await get_next_eventhub_arrival()

        logger.info(pprint.pformat(event))

        assert event.message_body == telemetry

        system_props = event.system_properties
        assert system_props[
            const.EVENTHUB_SYSPROP_DT_DATASCHEMA] == pnp_model_id
        assert system_props[
            const.EVENTHUB_SYSPROP_CONTENT_TYPE] == const.JSON_CONTENT_TYPE
        assert system_props[
            const.
            EVENTHUB_SYSPROP_CONTENT_ENCODING] == const.JSON_CONTENT_ENCODING
Beispiel #15
0
    async def test_send_message(self, client, service_helper, device_id,
                                module_id, event_loop):
        message = json.dumps(get_random_dict())

        received_message = None
        received = asyncio.Event()

        async def handle_on_message_received(message):
            nonlocal received_message, received
            logger.info("received {}".format(message))
            received_message = message
            event_loop.call_soon_threadsafe(received.set)

        client.on_message_received = handle_on_message_received

        await service_helper.send_c2d(device_id, module_id, message, {})

        await asyncio.wait_for(received.wait(), 10)

        assert received_message.data.decode("utf-8") == message
Beispiel #16
0
    def test_send_message(self, client, service_helper, device_id, module_id):
        message = json.dumps(get_random_dict())

        received = threading.Event()

        # hack needed because there is no `nonlocal` keyword in py27.
        nonlocal_py27_hack = {"received_msg": None, "received": received}

        def handle_on_message_received(message):
            logger.info("received {}".format(message))
            nonlocal_py27_hack["received_message"] = message
            nonlocal_py27_hack["received"].set()

        client.on_message_received = handle_on_message_received

        service_helper.send_c2d(device_id, module_id, message, {})

        received.wait(timeout=10)

        assert nonlocal_py27_hack["received_message"].data.decode(
            "utf-8") == message
Beispiel #17
0
    async def test_receive_desired_property_patch(
        self,
        event_loop,
        client,
        pnp_component_name,
        pnp_writable_property_name,
        is_component_property,
        pnp_ack_code,
        pnp_ack_description,
        service_helper,
        device_id,
        module_id,
    ):
        random_property_value = get_random_dict()
        received_patch = None
        received = asyncio.Event()

        async def handle_on_patch_received(patch):
            nonlocal received_patch, received
            logger.info("received {}".format(patch))
            received_patch = patch
            event_loop.call_soon_threadsafe(received.set)

        client.on_writable_property_update_request_received = handle_on_patch_received
        await asyncio.sleep(1)

        # patch desired properites
        props = make_pnp_desired_property_patch(
            pnp_component_name if is_component_property else None,
            pnp_writable_property_name,
            random_property_value,
        )
        await service_helper.update_pnp_properties(device_id, module_id, props)
        logger.info("patch sent. Waiting for desired proprety")

        # wait for the desired property patch to arrive at the client
        await asyncio.wait_for(received.wait(), 10)
        logger.info("got it")

        # validate the patch
        if is_component_property:
            assert (received_patch.get_component_property(
                pnp_component_name,
                pnp_writable_property_name) == random_property_value)
            assert received_patch.backing_object[pnp_component_name][
                "__t"] == "c"
        else:
            assert received_patch.get_property(
                pnp_writable_property_name) == random_property_value

        # make a reported property patch to respond
        update_patch = ClientPropertyCollection()
        property_response = generate_writable_property_response(
            random_property_value, pnp_ack_code, pnp_ack_description,
            received_patch.version)

        if is_component_property:
            update_patch.set_component_property(pnp_component_name,
                                                pnp_writable_property_name,
                                                property_response)
        else:
            update_patch.set_property(pnp_writable_property_name,
                                      property_response)

        # send the reported property patch
        await client.update_client_properties(update_patch)

        # verify that the reported value via digital_twin_client.get_digital_twin()
        props = await service_helper.get_pnp_properties(device_id, module_id)
        if is_component_property:
            props = props[pnp_component_name]

        assert props[pnp_writable_property_name] == random_property_value
        metadata = props["$metadata"][pnp_writable_property_name]
        assert metadata["ackCode"] == pnp_ack_code
        assert metadata["ackDescription"] == pnp_ack_description
        assert metadata["ackVersion"] == received_patch.version
        assert metadata["desiredVersion"] == received_patch.version
        assert metadata["desiredValue"] == random_property_value
Beispiel #18
0
def random_reported_props():
    return {const.TEST_CONTENT: get_random_dict()}