def test_central_monitor_events(self):
        (template_id, _) = self._create_device_template()
        (device_id, _) = self._create_device(instance_of=template_id)
        credentials = self._get_credentials(device_id)

        device_client = helpers.dps_connect_device(device_id, credentials)

        enqueued_time = utility.calculate_millisec_since_unix_epoch_utc(
        ) - 10000

        payload = {"Bool": True}
        msg = Message(
            data=json.dumps(payload),
            content_encoding="utf-8",
            content_type="application/json",
        )
        device_client.send_message(msg)

        # Test with invalid app-id
        self.cmd(
            "iot central diagnostics monitor-events --app-id {} -y".format(
                APP_ID + "zzz"),
            expect_failure=True,
        )

        # Ensure no failure
        output = self._get_monitor_events_output(device_id, enqueued_time)

        self._delete_device(device_id)
        self._delete_device_template(template_id)
        assert '"Bool": true' in output
        assert device_id in output
    def test_central_validate_messages_success(self):
        (template_id, _) = self._create_device_template()
        (device_id, _) = self._create_device(instance_of=template_id)
        credentials = self._get_credentials(device_id)

        device_client = helpers.dps_connect_device(device_id, credentials)

        enqueued_time = utility.calculate_millisec_since_unix_epoch_utc(
        ) - 10000

        payload = {"Bool": True}
        msg = Message(
            data=json.dumps(payload),
            content_encoding="utf-8",
            content_type="application/json",
        )
        device_client.send_message(msg)

        # Validate the messages
        output = self._get_validate_messages_output(device_id, enqueued_time)

        self._delete_device(device_id)
        self._delete_device_template(template_id)

        assert output
        assert "Successfully parsed 1 message(s)" in output
        assert "No errors detected" in output
Esempio n. 3
0
    def test_iothub_c2d_messages(self):
        device_count = 1
        device_ids = self.generate_device_names(device_count)

        self.cmd(
            f"iot hub device-identity create -d {device_ids[0]} -n {LIVE_HUB} -g {LIVE_RG}"
        )

        for auth_phase in DATAPLANE_AUTH_TYPES:
            test_ce = "utf-16" if auth_phase == AuthenticationTypeDataplane.login.value else "utf-8"
            test_body = f"{uuid4()} шеллы 😁"  # Mixed unicode blocks
            test_props = f"key0={str(uuid4())};key1={str(uuid4())}"
            test_cid = str(uuid4())
            test_mid = str(uuid4())
            test_ct = "text/plain"
            test_et = calculate_millisec_since_unix_epoch_utc(
                3600)  # milliseconds since epoch

            self.kwargs["c2d_json_send_data"] = json.dumps(
                {"data": str(uuid4())})

            # Send C2D message
            self.cmd(
                self.set_cmd_auth_type(
                    f"iot device c2d-message send -d {device_ids[0]} -n {LIVE_HUB} -g {LIVE_RG} --data '{test_body}' "
                    f"--cid {test_cid} --mid {test_mid} --ct {test_ct} --expiry {test_et} --ce {test_ce} -p '{test_props}'",
                    auth_type=auth_phase),
                checks=self.is_empty(),
            )

            c2d_receive_result = self.cmd(
                f"iot device c2d-message receive -d {device_ids[0]} --hub-name {LIVE_HUB} -g {LIVE_RG} --complete",
            ).get_output_in_json()

            assert c2d_receive_result["data"] == test_body

            # Assert system properties
            received_system_props = c2d_receive_result["properties"]["system"]
            assert received_system_props["ContentEncoding"] == test_ce
            assert received_system_props["ContentType"] == test_ct
            assert received_system_props["iothub-correlationid"] == test_cid
            assert received_system_props["iothub-messageid"] == test_mid
            assert received_system_props["iothub-expiry"]
            assert received_system_props[
                "iothub-to"] == f"/devices/{device_ids[0]}/messages/devicebound"

            # Ack is tested in message feedback tests
            assert received_system_props["iothub-ack"] == "none"

            # Assert app properties
            received_app_props = c2d_receive_result["properties"]["app"]
            assert received_app_props == validate_key_value_pairs(test_props)
            assert c2d_receive_result["etag"]
Esempio n. 4
0
    def test_hub_monitor_events(self):
        for cg in LIVE_CONSUMER_GROUPS:
            self.cmd(
                "az iot hub consumer-group create --hub-name {} --resource-group {} --name {}"
                .format(LIVE_HUB, LIVE_RG, cg),
                checks=[self.check("name", cg)],
            )

        from azext_iot.operations.hub import iot_device_send_message
        from azext_iot._factory import iot_hub_service_factory
        from azure.cli.core.mock import DummyCli

        cli_ctx = DummyCli()
        client = iot_hub_service_factory(cli_ctx)

        device_count = 10
        device_ids = self.generate_device_names(device_count)

        # Test with invalid connection string
        self.cmd(
            "iot hub monitor-events -t 1 -y --login {}".format(
                self.connection_string + "zzz"),
            expect_failure=True,
        )

        # Create and Simulate Devices
        for i in range(device_count):
            self.cmd(
                "iot hub device-identity create -d {} -n {} -g {}".format(
                    device_ids[i], LIVE_HUB, LIVE_RG),
                checks=[self.check("deviceId", device_ids[i])],
            )

        enqueued_time = calculate_millisec_since_unix_epoch_utc()

        for i in range(device_count):
            execute_onthread(
                method=iot_device_send_message,
                args=[
                    client,
                    device_ids[i],
                    LIVE_HUB,
                    '{\r\n"payload_data1":"payload_value1"\r\n}',
                    "$.mid=12345;key0=value0;key1=1",
                    1,
                    LIVE_RG,
                    None,
                    0,
                ],
                max_runs=1,
            )
        # Monitor events for all devices and include sys, anno, app
        self.command_execute_assert(
            "iot hub monitor-events -n {} -g {} --cg {} --et {} -t 5 -y -p sys anno app"
            .format(LIVE_HUB, LIVE_RG, LIVE_CONSUMER_GROUPS[0], enqueued_time),
            device_ids + [
                "system",
                "annotations",
                "application",
                '"message_id": "12345"',
                '"key0": "value0"',
                '"key1": "1"',
            ],
        )

        # Monitor events for a single device
        self.command_execute_assert(
            "iot hub monitor-events -n {} -g {} -d {} --cg {} --et {} -t 5 -y -p all"
            .format(LIVE_HUB, LIVE_RG, device_ids[0], LIVE_CONSUMER_GROUPS[1],
                    enqueued_time),
            [
                device_ids[0],
                "system",
                "annotations",
                "application",
                '"message_id": "12345"',
                '"key0": "value0"',
                '"key1": "1"',
            ],
        )

        # Monitor events with device-id wildcards
        self.command_execute_assert(
            "iot hub monitor-events -n {} -g {} -d {} --et {} -t 5 -y -p sys anno app"
            .format(LIVE_HUB, LIVE_RG, PREFIX_DEVICE + "*", enqueued_time),
            device_ids,
        )

        # Monitor events for specific devices using query language
        device_subset_include = device_ids[:device_count // 2]
        device_include_string = ", ".join(
            ["'" + deviceId + "'" for deviceId in device_subset_include])
        query_string = "select * from devices where deviceId in [{}]".format(
            device_include_string)

        self.command_execute_assert(
            'iot hub monitor-events -n {} -g {} --device-query "{}" --et {} -t 5 -y -p sys anno app'
            .format(LIVE_HUB, LIVE_RG, query_string, enqueued_time),
            device_subset_include,
        )

        # Expect failure for excluded devices
        device_subset_exclude = device_ids[device_count // 2:]
        with pytest.raises(Exception):
            self.command_execute_assert(
                'iot hub monitor-events -n {} -g {} --device-query "{}" --et {} -t 5 -y -p sys anno app'
                .format(LIVE_HUB, LIVE_RG, query_string, enqueued_time),
                device_subset_exclude,
            )

        # Monitor events with --login parameter
        self.command_execute_assert(
            "iot hub monitor-events -t 5 -y -p all --cg {} --et {} --login {}".
            format(LIVE_CONSUMER_GROUPS[2], enqueued_time,
                   self.connection_string),
            device_ids,
        )

        enqueued_time = calculate_millisec_since_unix_epoch_utc()

        # Send messages that have JSON payload, but do not pass $.ct property
        execute_onthread(
            method=iot_device_send_message,
            args=[
                client,
                device_ids[i],
                LIVE_HUB,
                '{\r\n"payload_data1":"payload_value1"\r\n}',
                "",
                1,
                LIVE_RG,
                None,
                1,
            ],
            max_runs=1,
        )

        # Monitor messages for ugly JSON output
        self.command_execute_assert(
            "iot hub monitor-events -n {} -g {} --cg {} --et {} -t 5 -y".
            format(LIVE_HUB, LIVE_RG, LIVE_CONSUMER_GROUPS[0], enqueued_time),
            ["\\r\\n"],
        )

        # Monitor messages and parse payload as JSON with the --ct parameter
        self.command_execute_assert(
            "iot hub monitor-events -n {} -g {} --cg {} --et {} -t 5 --ct application/json -y"
            .format(LIVE_HUB, LIVE_RG, LIVE_CONSUMER_GROUPS[1], enqueued_time),
            ['"payload_data1": "payload_value1"'],
        )

        enqueued_time = calculate_millisec_since_unix_epoch_utc()

        # Send messages that have JSON payload and have $.ct property
        execute_onthread(
            method=iot_device_send_message,
            args=[
                client,
                device_ids[i],
                LIVE_HUB,
                '{\r\n"payload_data1":"payload_value1"\r\n}',
                "$.ct=application/json",
                1,
                LIVE_RG,
            ],
            max_runs=1,
        )

        # Monitor messages for pretty JSON output
        self.command_execute_assert(
            "iot hub monitor-events -n {} -g {} --cg {} --et {} -t 5 -y".
            format(LIVE_HUB, LIVE_RG, LIVE_CONSUMER_GROUPS[0], enqueued_time),
            ['"payload_data1": "payload_value1"'],
        )

        # Monitor messages with yaml output
        self.command_execute_assert(
            "iot hub monitor-events -n {} -g {} --cg {} --et {} -t 5 -y -o yaml"
            .format(LIVE_HUB, LIVE_RG, LIVE_CONSUMER_GROUPS[1], enqueued_time),
            ["payload_data1: payload_value1"],
        )

        enqueued_time = calculate_millisec_since_unix_epoch_utc()

        # Send messages that have improperly formatted JSON payload and a $.ct property
        execute_onthread(
            method=iot_device_send_message,
            args=[
                client,
                device_ids[i],
                LIVE_HUB,
                '{\r\n"payload_data1""payload_value1"\r\n}',
                "$.ct=application/json",
                1,
                LIVE_RG,
            ],
            max_runs=1,
        )

        # Monitor messages to ensure it returns improperly formatted JSON
        self.command_execute_assert(
            "iot hub monitor-events -n {} -g {} --cg {} --et {} -t 5 -y".
            format(LIVE_HUB, LIVE_RG, LIVE_CONSUMER_GROUPS[0], enqueued_time),
            ['{\\r\\n\\"payload_data1\\"\\"payload_value1\\"\\r\\n}'],
        )

        for cg in LIVE_CONSUMER_GROUPS:
            self.cmd(
                "az iot hub consumer-group delete --hub-name {} --resource-group {} --name {}"
                .format(LIVE_HUB, LIVE_RG, cg),
                expect_failure=False,
            )
    def test_central_validate_messages_issues_detected(self):
        expected_messages = []
        (template_id, _) = self._create_device_template()
        (device_id, _) = self._create_device(instance_of=template_id)
        credentials = self._get_credentials(device_id)

        device_client = helpers.dps_connect_device(device_id, credentials)

        enqueued_time = utility.calculate_millisec_since_unix_epoch_utc(
        ) - 10000

        # Invalid encoding
        payload = {"Bool": True}
        msg = Message(data=json.dumps(payload),
                      content_type="application/json")
        device_client.send_message(msg)
        expected_messages.append(strings.invalid_encoding(""))

        # Content type mismatch (e.g. non application/json)
        payload = {"Bool": True}
        msg = Message(data=json.dumps(payload), content_encoding="utf-8")
        device_client.send_message(msg)
        expected_messages.append(
            strings.content_type_mismatch("", "application/json"))

        # Invalid type
        payload = {"Bool": 123}
        msg = Message(
            data=json.dumps(payload),
            content_encoding="utf-8",
            content_type="application/json",
        )
        device_client.send_message(msg)
        expected_messages.append(
            strings.invalid_primitive_schema_mismatch_template(
                "Bool", "boolean", 123))

        # Telemetry not defined
        payload = {"NotPresentInTemplate": True}
        msg = Message(
            data=json.dumps(payload),
            content_encoding="utf-8",
            content_type="application/json",
        )
        device_client.send_message(msg)
        # this error is harder to build from strings because we have to construct a whole template for it
        expected_messages.append(
            "Following capabilities have NOT been defined in the device template '['NotPresentInTemplate']'"
        )

        # Invalid JSON
        payload = '{"asd":"def}'
        msg = Message(
            data=payload,
            content_encoding="utf-8",
            content_type="application/json",
        )
        device_client.send_message(msg)
        expected_messages.append(strings.invalid_json())

        # Validate the messages
        output = self._get_validate_messages_output(
            device_id, enqueued_time, max_messages=len(expected_messages))

        self._delete_device(device_id)
        self._delete_device_template(template_id)

        assert output

        expected_issues = [
            "No encoding found. Expected encoding 'utf-8' to be present in message header.",
            "Content type '' is not supported. Expected Content type is 'application/json'.",
            "Datatype of telemetry field 'Bool' does not match the datatype boolean.",
            "Data sent by the device : 123.",
            "For more information, see: https://aka.ms/iotcentral-payloads",
            "Following capabilities have NOT been defined in the device template '['NotPresentInTemplate']'",
            "Invalid JSON format",
        ]
        for issue in expected_issues:
            assert issue in output