From 54273fa88169ccbaf588c1d615601ecff26c135d Mon Sep 17 00:00:00 2001 From: Carter Tinney Date: Mon, 15 Jul 2024 13:16:29 -0700 Subject: [PATCH 1/5] Removed ptyest-asyncio restriction --- requirements_test.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements_test.txt b/requirements_test.txt index ea6d086a5..f489cfb2e 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,5 +1,5 @@ -pytest < 8.0.0 -pytest-asyncio <= 0.16 +pytest < 9.0.0 +pytest-asyncio pytest-mock pytest-testdox>=1.1.1 pytest-cov From cf689f107d3d5f594a436b516a32ea49e09a8e84 Mon Sep 17 00:00:00 2001 From: Carter Tinney Date: Mon, 15 Jul 2024 13:29:05 -0700 Subject: [PATCH 2/5] removed unnecessary manual pytestmark --- pytest.ini | 1 + tests/unit/common/test_async_adapter.py | 1 - tests/unit/iothub/aio/test_async_clients.py | 1 - tests/unit/iothub/aio/test_async_handler_manager.py | 1 - .../provisioning/aio/test_async_provisioning_device_client.py | 1 - 5 files changed, 1 insertion(+), 4 deletions(-) diff --git a/pytest.ini b/pytest.ini index 07ac113a3..23108d61e 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,4 +1,5 @@ [pytest] +asyncio_mode=auto testdox_format = plaintext addopts = --testdox --timeout 20 --ignore e2e --ignore tests/e2e norecursedirs=__pycache__, *.egg-info diff --git a/tests/unit/common/test_async_adapter.py b/tests/unit/common/test_async_adapter.py index 800b85d42..d90a895e4 100644 --- a/tests/unit/common/test_async_adapter.py +++ b/tests/unit/common/test_async_adapter.py @@ -11,7 +11,6 @@ import azure.iot.device.common.async_adapter as async_adapter logging.basicConfig(level=logging.DEBUG) -pytestmark = pytest.mark.asyncio @pytest.fixture diff --git a/tests/unit/iothub/aio/test_async_clients.py b/tests/unit/iothub/aio/test_async_clients.py index b22d1774e..3796f494a 100644 --- a/tests/unit/iothub/aio/test_async_clients.py +++ b/tests/unit/iothub/aio/test_async_clients.py @@ -44,7 +44,6 @@ SharedIoTHubModuleClientCreateFromEdgeEnvironmentWithDebugEnvTests, ) -pytestmark = pytest.mark.asyncio logging.basicConfig(level=logging.DEBUG) diff --git a/tests/unit/iothub/aio/test_async_handler_manager.py b/tests/unit/iothub/aio/test_async_handler_manager.py index b3dc5c056..781b902ab 100644 --- a/tests/unit/iothub/aio/test_async_handler_manager.py +++ b/tests/unit/iothub/aio/test_async_handler_manager.py @@ -16,7 +16,6 @@ from azure.iot.device.iothub.inbox_manager import InboxManager from azure.iot.device.iothub.aio.async_inbox import AsyncClientInbox -pytestmark = pytest.mark.asyncio logging.basicConfig(level=logging.DEBUG) # NOTE ON TEST IMPLEMENTATION: diff --git a/tests/unit/provisioning/aio/test_async_provisioning_device_client.py b/tests/unit/provisioning/aio/test_async_provisioning_device_client.py index 2b1106a52..75ebc5107 100644 --- a/tests/unit/provisioning/aio/test_async_provisioning_device_client.py +++ b/tests/unit/provisioning/aio/test_async_provisioning_device_client.py @@ -20,7 +20,6 @@ logging.basicConfig(level=logging.DEBUG) -pytestmark = pytest.mark.asyncio async def create_completed_future(result=None): From 8cfd2bc4617dbafab19f6c23254eb04af9a1a1c0 Mon Sep 17 00:00:00 2001 From: Carter Tinney Date: Mon, 15 Jul 2024 13:30:38 -0700 Subject: [PATCH 3/5] Removed unnecessary manual pytestmark from E2E --- tests/e2e/iothub_e2e/aio/test_c2d.py | 1 - tests/e2e/iothub_e2e/aio/test_connect_disconnect.py | 2 -- tests/e2e/iothub_e2e/aio/test_connect_disconnect_stress.py | 2 -- tests/e2e/iothub_e2e/aio/test_infrastructure.py | 2 -- tests/e2e/iothub_e2e/aio/test_methods.py | 2 -- tests/e2e/iothub_e2e/aio/test_sas_renewal.py | 2 -- tests/e2e/iothub_e2e/aio/test_send_message.py | 2 -- tests/e2e/iothub_e2e/aio/test_send_message_stress.py | 1 - tests/e2e/iothub_e2e/aio/test_twin.py | 2 -- tests/e2e/iothub_e2e/aio/test_twin_stress.py | 2 -- .../tests/test_async_certificate_enrollments.py | 1 - .../provisioning_e2e/tests/test_async_symmetric_enrollments.py | 2 +- 12 files changed, 1 insertion(+), 20 deletions(-) diff --git a/tests/e2e/iothub_e2e/aio/test_c2d.py b/tests/e2e/iothub_e2e/aio/test_c2d.py index 980ccc583..07905e135 100644 --- a/tests/e2e/iothub_e2e/aio/test_c2d.py +++ b/tests/e2e/iothub_e2e/aio/test_c2d.py @@ -10,7 +10,6 @@ logger = logging.getLogger(__name__) logger.setLevel(level=logging.INFO) -pytestmark = pytest.mark.asyncio # TODO: add tests for various application properties # TODO: is there a way to call send_c2d so it arrives as an object rather than a JSON string? diff --git a/tests/e2e/iothub_e2e/aio/test_connect_disconnect.py b/tests/e2e/iothub_e2e/aio/test_connect_disconnect.py index 89d3d267b..01df331de 100644 --- a/tests/e2e/iothub_e2e/aio/test_connect_disconnect.py +++ b/tests/e2e/iothub_e2e/aio/test_connect_disconnect.py @@ -9,8 +9,6 @@ logger = logging.getLogger(__name__) logger.setLevel(level=logging.INFO) -pytestmark = pytest.mark.asyncio - @pytest.mark.describe("Client object") class TestConnectDisconnect(object): diff --git a/tests/e2e/iothub_e2e/aio/test_connect_disconnect_stress.py b/tests/e2e/iothub_e2e/aio/test_connect_disconnect_stress.py index c4d1f5caf..0e4e1d2fd 100644 --- a/tests/e2e/iothub_e2e/aio/test_connect_disconnect_stress.py +++ b/tests/e2e/iothub_e2e/aio/test_connect_disconnect_stress.py @@ -10,8 +10,6 @@ logger = logging.getLogger(__name__) logger.setLevel(level=logging.INFO) -pytestmark = pytest.mark.asyncio - @pytest.mark.stress @pytest.mark.describe("Client object connect/disconnect stress") diff --git a/tests/e2e/iothub_e2e/aio/test_infrastructure.py b/tests/e2e/iothub_e2e/aio/test_infrastructure.py index 5ace0aebf..1587d5c71 100644 --- a/tests/e2e/iothub_e2e/aio/test_infrastructure.py +++ b/tests/e2e/iothub_e2e/aio/test_infrastructure.py @@ -4,8 +4,6 @@ import pytest import uuid -pytestmark = pytest.mark.asyncio - @pytest.mark.describe("ServiceHelper object") class TestServiceHelper(object): diff --git a/tests/e2e/iothub_e2e/aio/test_methods.py b/tests/e2e/iothub_e2e/aio/test_methods.py index 50e7f487c..4ca196dab 100644 --- a/tests/e2e/iothub_e2e/aio/test_methods.py +++ b/tests/e2e/iothub_e2e/aio/test_methods.py @@ -11,8 +11,6 @@ logger = logging.getLogger(__name__) logger.setLevel(level=logging.INFO) -pytestmark = pytest.mark.asyncio - @pytest.fixture def method_name(): diff --git a/tests/e2e/iothub_e2e/aio/test_sas_renewal.py b/tests/e2e/iothub_e2e/aio/test_sas_renewal.py index e7942b150..faabe343a 100644 --- a/tests/e2e/iothub_e2e/aio/test_sas_renewal.py +++ b/tests/e2e/iothub_e2e/aio/test_sas_renewal.py @@ -11,8 +11,6 @@ logger = logging.getLogger(__name__) logger.setLevel(level=logging.INFO) -pytestmark = pytest.mark.asyncio - @pytest.mark.skipif( test_config.config.auth not in test_config.AUTH_WITH_RENEWING_TOKEN, diff --git a/tests/e2e/iothub_e2e/aio/test_send_message.py b/tests/e2e/iothub_e2e/aio/test_send_message.py index 40bb2daa2..bc609e9c9 100644 --- a/tests/e2e/iothub_e2e/aio/test_send_message.py +++ b/tests/e2e/iothub_e2e/aio/test_send_message.py @@ -11,8 +11,6 @@ logger = logging.getLogger(__name__) logger.setLevel(level=logging.INFO) -pytestmark = pytest.mark.asyncio - @pytest.mark.describe("Client send_message method") class TestSendMessage(object): diff --git a/tests/e2e/iothub_e2e/aio/test_send_message_stress.py b/tests/e2e/iothub_e2e/aio/test_send_message_stress.py index 81d7aacb9..64beb7025 100644 --- a/tests/e2e/iothub_e2e/aio/test_send_message_stress.py +++ b/tests/e2e/iothub_e2e/aio/test_send_message_stress.py @@ -15,7 +15,6 @@ logger = logging.getLogger(__name__) logger.setLevel(level=logging.INFO) -pytestmark = pytest.mark.asyncio # Settings that apply to all tests in this module TELEMETRY_PAYLOAD_SIZE = 16 * 1024 diff --git a/tests/e2e/iothub_e2e/aio/test_twin.py b/tests/e2e/iothub_e2e/aio/test_twin.py index 92b798910..a16e9b136 100644 --- a/tests/e2e/iothub_e2e/aio/test_twin.py +++ b/tests/e2e/iothub_e2e/aio/test_twin.py @@ -11,8 +11,6 @@ logger = logging.getLogger(__name__) logger.setLevel(level=logging.INFO) -pytestmark = pytest.mark.asyncio - # TODO: tests with drop_incoming and reject_incoming diff --git a/tests/e2e/iothub_e2e/aio/test_twin_stress.py b/tests/e2e/iothub_e2e/aio/test_twin_stress.py index b873becf2..db0858203 100644 --- a/tests/e2e/iothub_e2e/aio/test_twin_stress.py +++ b/tests/e2e/iothub_e2e/aio/test_twin_stress.py @@ -12,8 +12,6 @@ logger = logging.getLogger(__name__) logger.setLevel(level=logging.INFO) -pytestmark = pytest.mark.asyncio - @pytest.fixture def toxic(): diff --git a/tests/e2e/provisioning_e2e/tests/test_async_certificate_enrollments.py b/tests/e2e/provisioning_e2e/tests/test_async_certificate_enrollments.py index 1b8ea4ab3..0219af14e 100644 --- a/tests/e2e/provisioning_e2e/tests/test_async_certificate_enrollments.py +++ b/tests/e2e/provisioning_e2e/tests/test_async_certificate_enrollments.py @@ -29,7 +29,6 @@ ) -pytestmark = pytest.mark.asyncio logging.basicConfig(level=logging.DEBUG) diff --git a/tests/e2e/provisioning_e2e/tests/test_async_symmetric_enrollments.py b/tests/e2e/provisioning_e2e/tests/test_async_symmetric_enrollments.py index 3657db15b..914a158d5 100644 --- a/tests/e2e/provisioning_e2e/tests/test_async_symmetric_enrollments.py +++ b/tests/e2e/provisioning_e2e/tests/test_async_symmetric_enrollments.py @@ -13,7 +13,7 @@ import os import uuid -pytestmark = pytest.mark.asyncio + logging.basicConfig(level=logging.DEBUG) From 39d94f65938a5a3a1aadd8ee5867d91f3b35e9b9 Mon Sep 17 00:00:00 2001 From: Carter Tinney Date: Mon, 15 Jul 2024 13:52:06 -0700 Subject: [PATCH 4/5] Removed use of deprecated APIs/constants --- azure-iot-device/azure/iot/device/common/http_transport.py | 6 ++---- azure-iot-device/azure/iot/device/common/mqtt_transport.py | 6 ++---- tests/e2e/iothub_e2e/sync/conftest.py | 2 +- tests/unit/common/test_http_transport.py | 7 +++---- tests/unit/common/test_mqtt_transport.py | 6 +++--- 5 files changed, 11 insertions(+), 16 deletions(-) diff --git a/azure-iot-device/azure/iot/device/common/http_transport.py b/azure-iot-device/azure/iot/device/common/http_transport.py index d09629f0e..a4d3cebc1 100644 --- a/azure-iot-device/azure/iot/device/common/http_transport.py +++ b/azure-iot-device/azure/iot/device/common/http_transport.py @@ -69,7 +69,8 @@ def _create_ssl_context(self): This method creates the SSLContext object used to authenticate the connection. The generated context is used by the http_client and is necessary when authenticating using a self-signed X509 cert or trusted X509 cert """ logger.debug("creating a SSL context") - ssl_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLSv1_2) + # Note that PROTOCOL_TLS_CLIENT implies ssl.CERT_REQUIRED and check_hostname == true + ssl_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT) if self._server_verification_cert: ssl_context.load_verify_locations(cadata=self._server_verification_cert) @@ -91,9 +92,6 @@ def _create_ssl_context(self): self._x509_cert.pass_phrase, ) - ssl_context.verify_mode = ssl.CERT_REQUIRED - ssl_context.check_hostname = True - return ssl_context @pipeline_thread.invoke_on_http_thread_nowait diff --git a/azure-iot-device/azure/iot/device/common/mqtt_transport.py b/azure-iot-device/azure/iot/device/common/mqtt_transport.py index cf54a0416..0d3b4dd76 100644 --- a/azure-iot-device/azure/iot/device/common/mqtt_transport.py +++ b/azure-iot-device/azure/iot/device/common/mqtt_transport.py @@ -321,7 +321,8 @@ def _create_ssl_context(self): This method creates the SSLContext object used by Paho to authenticate the connection. """ logger.debug("creating a SSL context") - ssl_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLSv1_2) + # Note that PROTOCOL_TLS_CLIENT implies ssl.CERT_REQUIRED and check_hostname == true + ssl_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT) if self._server_verification_cert: logger.debug("configuring SSL context with custom server verification cert") @@ -346,9 +347,6 @@ def _create_ssl_context(self): self._x509_cert.pass_phrase, ) - ssl_context.verify_mode = ssl.CERT_REQUIRED - ssl_context.check_hostname = True - return ssl_context def shutdown(self): diff --git a/tests/e2e/iothub_e2e/sync/conftest.py b/tests/e2e/iothub_e2e/sync/conftest.py index d04d9c5cd..b271d8aea 100644 --- a/tests/e2e/iothub_e2e/sync/conftest.py +++ b/tests/e2e/iothub_e2e/sync/conftest.py @@ -20,7 +20,7 @@ def brand_new_client(device_identity, client_kwargs, service_helper, device_id, # Keep this here. It is useful to see this info inside the inside devops pipeline test failures. logger.info( "Connecting device_id={}, module_id={}, to hub={} at {} (UTC)".format( - device_id, module_id, test_env.IOTHUB_HOSTNAME, datetime.datetime.utcnow() + device_id, module_id, test_env.IOTHUB_HOSTNAME, datetime.datetime.now(datetime.UTC) ) ) diff --git a/tests/unit/common/test_http_transport.py b/tests/unit/common/test_http_transport.py index 9f89d14b9..1dbee2d8b 100644 --- a/tests/unit/common/test_http_transport.py +++ b/tests/unit/common/test_http_transport.py @@ -100,14 +100,13 @@ def test_proxy_format(self, proxy_options): ) def test_configures_tls_context(self, mocker): mock_ssl_context_constructor = mocker.patch.object(ssl, "SSLContext") - mock_ssl_context = mock_ssl_context_constructor.return_value HTTPTransport(hostname=fake_hostname) # Verify correctness of TLS/SSL Context assert mock_ssl_context_constructor.call_count == 1 - assert mock_ssl_context_constructor.call_args == mocker.call(protocol=ssl.PROTOCOL_TLSv1_2) - assert mock_ssl_context.check_hostname is True - assert mock_ssl_context.verify_mode == ssl.CERT_REQUIRED + assert mock_ssl_context_constructor.call_args == mocker.call( + protocol=ssl.PROTOCOL_TLS_CLIENT + ) @pytest.mark.it( "Configures TLS/SSL context using default certificates if protocol wrapper not instantiated with a server verification certificate" diff --git a/tests/unit/common/test_mqtt_transport.py b/tests/unit/common/test_mqtt_transport.py index ee547d03a..12aea49ac 100644 --- a/tests/unit/common/test_mqtt_transport.py +++ b/tests/unit/common/test_mqtt_transport.py @@ -267,9 +267,9 @@ def test_configures_tls_context(self, mocker): # Verify correctness of TLS/SSL Context assert mock_ssl_context_constructor.call_count == 1 - assert mock_ssl_context_constructor.call_args == mocker.call(protocol=ssl.PROTOCOL_TLSv1_2) - assert mock_ssl_context.check_hostname is True - assert mock_ssl_context.verify_mode == ssl.CERT_REQUIRED + assert mock_ssl_context_constructor.call_args == mocker.call( + protocol=ssl.PROTOCOL_TLS_CLIENT + ) # Verify context has been set assert mock_mqtt_client.tls_set_context.call_count == 1 From a658a99293e98dd1e8c1add3b6a90dffa4a43d81 Mon Sep 17 00:00:00 2001 From: Carter Tinney Date: Wed, 17 Jul 2024 08:10:04 -0700 Subject: [PATCH 5/5] reverted some changes --- azure-iot-device/azure/iot/device/common/http_transport.py | 6 ++++-- azure-iot-device/azure/iot/device/common/mqtt_transport.py | 6 ++++-- tests/e2e/iothub_e2e/sync/conftest.py | 2 +- tests/unit/common/test_http_transport.py | 7 ++++--- tests/unit/common/test_mqtt_transport.py | 6 +++--- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/azure-iot-device/azure/iot/device/common/http_transport.py b/azure-iot-device/azure/iot/device/common/http_transport.py index a4d3cebc1..d09629f0e 100644 --- a/azure-iot-device/azure/iot/device/common/http_transport.py +++ b/azure-iot-device/azure/iot/device/common/http_transport.py @@ -69,8 +69,7 @@ def _create_ssl_context(self): This method creates the SSLContext object used to authenticate the connection. The generated context is used by the http_client and is necessary when authenticating using a self-signed X509 cert or trusted X509 cert """ logger.debug("creating a SSL context") - # Note that PROTOCOL_TLS_CLIENT implies ssl.CERT_REQUIRED and check_hostname == true - ssl_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT) + ssl_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLSv1_2) if self._server_verification_cert: ssl_context.load_verify_locations(cadata=self._server_verification_cert) @@ -92,6 +91,9 @@ def _create_ssl_context(self): self._x509_cert.pass_phrase, ) + ssl_context.verify_mode = ssl.CERT_REQUIRED + ssl_context.check_hostname = True + return ssl_context @pipeline_thread.invoke_on_http_thread_nowait diff --git a/azure-iot-device/azure/iot/device/common/mqtt_transport.py b/azure-iot-device/azure/iot/device/common/mqtt_transport.py index 0d3b4dd76..cf54a0416 100644 --- a/azure-iot-device/azure/iot/device/common/mqtt_transport.py +++ b/azure-iot-device/azure/iot/device/common/mqtt_transport.py @@ -321,8 +321,7 @@ def _create_ssl_context(self): This method creates the SSLContext object used by Paho to authenticate the connection. """ logger.debug("creating a SSL context") - # Note that PROTOCOL_TLS_CLIENT implies ssl.CERT_REQUIRED and check_hostname == true - ssl_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT) + ssl_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLSv1_2) if self._server_verification_cert: logger.debug("configuring SSL context with custom server verification cert") @@ -347,6 +346,9 @@ def _create_ssl_context(self): self._x509_cert.pass_phrase, ) + ssl_context.verify_mode = ssl.CERT_REQUIRED + ssl_context.check_hostname = True + return ssl_context def shutdown(self): diff --git a/tests/e2e/iothub_e2e/sync/conftest.py b/tests/e2e/iothub_e2e/sync/conftest.py index b271d8aea..d04d9c5cd 100644 --- a/tests/e2e/iothub_e2e/sync/conftest.py +++ b/tests/e2e/iothub_e2e/sync/conftest.py @@ -20,7 +20,7 @@ def brand_new_client(device_identity, client_kwargs, service_helper, device_id, # Keep this here. It is useful to see this info inside the inside devops pipeline test failures. logger.info( "Connecting device_id={}, module_id={}, to hub={} at {} (UTC)".format( - device_id, module_id, test_env.IOTHUB_HOSTNAME, datetime.datetime.now(datetime.UTC) + device_id, module_id, test_env.IOTHUB_HOSTNAME, datetime.datetime.utcnow() ) ) diff --git a/tests/unit/common/test_http_transport.py b/tests/unit/common/test_http_transport.py index 1dbee2d8b..9f89d14b9 100644 --- a/tests/unit/common/test_http_transport.py +++ b/tests/unit/common/test_http_transport.py @@ -100,13 +100,14 @@ def test_proxy_format(self, proxy_options): ) def test_configures_tls_context(self, mocker): mock_ssl_context_constructor = mocker.patch.object(ssl, "SSLContext") + mock_ssl_context = mock_ssl_context_constructor.return_value HTTPTransport(hostname=fake_hostname) # Verify correctness of TLS/SSL Context assert mock_ssl_context_constructor.call_count == 1 - assert mock_ssl_context_constructor.call_args == mocker.call( - protocol=ssl.PROTOCOL_TLS_CLIENT - ) + assert mock_ssl_context_constructor.call_args == mocker.call(protocol=ssl.PROTOCOL_TLSv1_2) + assert mock_ssl_context.check_hostname is True + assert mock_ssl_context.verify_mode == ssl.CERT_REQUIRED @pytest.mark.it( "Configures TLS/SSL context using default certificates if protocol wrapper not instantiated with a server verification certificate" diff --git a/tests/unit/common/test_mqtt_transport.py b/tests/unit/common/test_mqtt_transport.py index 12aea49ac..ee547d03a 100644 --- a/tests/unit/common/test_mqtt_transport.py +++ b/tests/unit/common/test_mqtt_transport.py @@ -267,9 +267,9 @@ def test_configures_tls_context(self, mocker): # Verify correctness of TLS/SSL Context assert mock_ssl_context_constructor.call_count == 1 - assert mock_ssl_context_constructor.call_args == mocker.call( - protocol=ssl.PROTOCOL_TLS_CLIENT - ) + assert mock_ssl_context_constructor.call_args == mocker.call(protocol=ssl.PROTOCOL_TLSv1_2) + assert mock_ssl_context.check_hostname is True + assert mock_ssl_context.verify_mode == ssl.CERT_REQUIRED # Verify context has been set assert mock_mqtt_client.tls_set_context.call_count == 1