From 1ab8b27ed17bb089260e228ebcaa8212cbacf2ba Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Wed, 28 Jul 2021 16:54:57 -0700 Subject: [PATCH 1/6] make core tests offline --- .../async_tests/test_basic_transport_async.py | 11 -- .../tests/async_tests/test_pipeline_async.py | 75 ---------- .../async_tests/test_retry_policy_async.py | 4 +- .../test_tracing_decorator_async.py | 2 +- .../async_tests/test_universal_http_async.py | 52 ------- .../azure-core/tests/test_basic_transport.py | 51 ------- .../tests/test_custom_hook_policy.py | 36 +++-- sdk/core/azure-core/tests/test_exceptions.py | 11 -- .../tests/test_requests_universal.py | 6 - .../azure-core/tests/test_retry_policy.py | 4 +- .../tests/test_tracing_decorator.py | 2 +- .../test_basic_transport_async_test_server.py | 27 ++++ .../test_pipeline_async_test_server.py | 132 ++++++++++++++++++ .../test_universal_http_async_test_server.py | 91 ++++++++++++ .../test_basic_transport_test_server.py | 66 +++++++++ .../test_exceptions_test_server.py | 40 ++++++ .../test_requests_universal_test_server.py | 33 +++++ 17 files changed, 418 insertions(+), 225 deletions(-) create mode 100644 sdk/core/azure-core/tests/testserver_tests/async_tests/test_basic_transport_async_test_server.py create mode 100644 sdk/core/azure-core/tests/testserver_tests/async_tests/test_pipeline_async_test_server.py create mode 100644 sdk/core/azure-core/tests/testserver_tests/async_tests/test_universal_http_async_test_server.py create mode 100644 sdk/core/azure-core/tests/testserver_tests/test_basic_transport_test_server.py create mode 100644 sdk/core/azure-core/tests/testserver_tests/test_exceptions_test_server.py create mode 100644 sdk/core/azure-core/tests/testserver_tests/test_requests_universal_test_server.py diff --git a/sdk/core/azure-core/tests/async_tests/test_basic_transport_async.py b/sdk/core/azure-core/tests/async_tests/test_basic_transport_async.py index 90dbfc0ec6e6..4f89cc552fd7 100644 --- a/sdk/core/azure-core/tests/async_tests/test_basic_transport_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_basic_transport_async.py @@ -41,17 +41,6 @@ def body(self): return self._body -@pytest.mark.asyncio -async def test_basic_options_aiohttp(): - - request = HttpRequest("OPTIONS", "https://httpbin.org") - async with AsyncPipeline(AioHttpTransport(), policies=[]) as pipeline: - response = await pipeline.run(request) - - assert pipeline._transport.session is None - assert isinstance(response.http_response.status_code, int) - - @pytest.mark.asyncio async def test_multipart_send(): transport = MockAsyncHttpTransport() diff --git a/sdk/core/azure-core/tests/async_tests/test_pipeline_async.py b/sdk/core/azure-core/tests/async_tests/test_pipeline_async.py index ee3a97b953ff..96d71cfa3973 100644 --- a/sdk/core/azure-core/tests/async_tests/test_pipeline_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_pipeline_async.py @@ -88,54 +88,6 @@ def on_exception(self, requests, **kwargs): with pytest.raises(NotImplementedError): await pipeline.run(req) - -@pytest.mark.asyncio -async def test_basic_aiohttp(): - - request = HttpRequest("GET", "https://bing.com") - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - async with AsyncPipeline(AioHttpTransport(), policies=policies) as pipeline: - response = await pipeline.run(request) - - assert pipeline._transport.session is None - # all we need to check is if we are able to make the call - assert isinstance(response.http_response.status_code, int) - -@pytest.mark.asyncio -async def test_basic_aiohttp_separate_session(): - - session = aiohttp.ClientSession() - request = HttpRequest("GET", "https://bing.com") - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - transport = AioHttpTransport(session=session, session_owner=False) - async with AsyncPipeline(transport, policies=policies) as pipeline: - response = await pipeline.run(request) - - assert transport.session - assert isinstance(response.http_response.status_code, int) - await transport.close() - assert transport.session - await transport.session.close() - -@pytest.mark.asyncio -async def test_basic_async_requests(): - - request = HttpRequest("GET", "https://bing.com") - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - async with AsyncPipeline(AsyncioRequestsTransport(), policies=policies) as pipeline: - response = await pipeline.run(request) - - assert isinstance(response.http_response.status_code, int) - @pytest.mark.asyncio async def test_async_transport_sleep(): @@ -185,33 +137,6 @@ def test_pass_in_http_logging_policy(): http_logging_policy = pipeline._impl_policies[-1]._policy assert http_logging_policy.allowed_header_names == HttpLoggingPolicy.DEFAULT_HEADERS_WHITELIST.union({"x-ms-added-header"}) -@pytest.mark.asyncio -async def test_conf_async_requests(): - - request = HttpRequest("GET", "https://bing.com/") - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - async with AsyncPipeline(AsyncioRequestsTransport(), policies=policies) as pipeline: - response = await pipeline.run(request) - - assert isinstance(response.http_response.status_code, int) - -def test_conf_async_trio_requests(): - - async def do(): - request = HttpRequest("GET", "https://bing.com/") - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - async with AsyncPipeline(TrioRequestsTransport(), policies=policies) as pipeline: - return await pipeline.run(request) - - response = trio.run(do) - assert isinstance(response.http_response.status_code, int) - @pytest.mark.asyncio async def test_retry_without_http_response(): class NaughtyPolicy(AsyncHTTPPolicy): diff --git a/sdk/core/azure-core/tests/async_tests/test_retry_policy_async.py b/sdk/core/azure-core/tests/async_tests/test_retry_policy_async.py index e23a1a35ee46..b77ee80d4bb7 100644 --- a/sdk/core/azure-core/tests/async_tests/test_retry_policy_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_retry_policy_async.py @@ -62,7 +62,7 @@ def test_retry_types(): @pytest.mark.parametrize("retry_after_input", [('0'), ('800'), ('1000'), ('1200')]) def test_retry_after(retry_after_input): retry_policy = AsyncRetryPolicy() - request = HttpRequest("GET", "https://bing.com") + request = HttpRequest("GET", "http://127.0.0.1") response = HttpResponse(request, None) response.headers["retry-after-ms"] = retry_after_input pipeline_response = PipelineResponse(request, response, None) @@ -80,7 +80,7 @@ def test_retry_after(retry_after_input): @pytest.mark.parametrize("retry_after_input", [('0'), ('800'), ('1000'), ('1200')]) def test_x_ms_retry_after(retry_after_input): retry_policy = AsyncRetryPolicy() - request = HttpRequest("GET", "https://bing.com") + request = HttpRequest("GET", "http://127.0.0.1") response = HttpResponse(request, None) response.headers["x-ms-retry-after-ms"] = retry_after_input pipeline_response = PipelineResponse(request, response, None) diff --git a/sdk/core/azure-core/tests/async_tests/test_tracing_decorator_async.py b/sdk/core/azure-core/tests/async_tests/test_tracing_decorator_async.py index fa251d96e770..e1b602268379 100644 --- a/sdk/core/azure-core/tests/async_tests/test_tracing_decorator_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_tracing_decorator_async.py @@ -31,7 +31,7 @@ class MockClient: @distributed_trace def __init__(self, policies=None, assert_current_span=False): time.sleep(0.001) - self.request = HttpRequest("GET", "https://bing.com") + self.request = HttpRequest("GET", "http://127.0.0.1") if policies is None: policies = [] policies.append(mock.Mock(spec=HTTPPolicy, send=self.verify_request)) diff --git a/sdk/core/azure-core/tests/async_tests/test_universal_http_async.py b/sdk/core/azure-core/tests/async_tests/test_universal_http_async.py index 64f003ad783b..f6c27b18cabd 100644 --- a/sdk/core/azure-core/tests/async_tests/test_universal_http_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_universal_http_async.py @@ -40,58 +40,6 @@ from unittest import mock -@pytest.mark.asyncio -async def test_basic_aiohttp(): - - request = HttpRequest("GET", "https://www.bing.com/") - async with AioHttpTransport() as sender: - response = await sender.send(request) - assert response.body() is not None - - assert sender.session is None - assert isinstance(response.status_code, int) - -@pytest.mark.asyncio -async def test_aiohttp_auto_headers(): - - request = HttpRequest("POST", "https://www.bing.com/") - async with AioHttpTransport() as sender: - response = await sender.send(request) - auto_headers = response.internal_response.request_info.headers - assert 'Content-Type' not in auto_headers - -@pytest.mark.asyncio -async def test_basic_async_requests(): - - request = HttpRequest("GET", "https://www.bing.com/") - async with AsyncioRequestsTransport() as sender: - response = await sender.send(request) - assert response.body() is not None - - assert isinstance(response.status_code, int) - -@pytest.mark.asyncio -async def test_conf_async_requests(): - - request = HttpRequest("GET", "https://www.bing.com/") - async with AsyncioRequestsTransport() as sender: - response = await sender.send(request) - assert response.body() is not None - - assert isinstance(response.status_code, int) - -def test_conf_async_trio_requests(): - - async def do(): - request = HttpRequest("GET", "https://www.bing.com/") - async with TrioRequestsTransport() as sender: - return await sender.send(request) - assert response.body() is not None - - response = trio.run(do) - assert isinstance(response.status_code, int) - - def _create_aiohttp_response(body_bytes, headers=None): class MockAiohttpClientResponse(aiohttp.ClientResponse): def __init__(self, body_bytes, headers=None): diff --git a/sdk/core/azure-core/tests/test_basic_transport.py b/sdk/core/azure-core/tests/test_basic_transport.py index d08feda5493f..d7c08e5ae601 100644 --- a/sdk/core/azure-core/tests/test_basic_transport.py +++ b/sdk/core/azure-core/tests/test_basic_transport.py @@ -96,27 +96,6 @@ def test_url_join(): assert _urljoin('devstoreaccount1/', 'testdir/') == 'devstoreaccount1/testdir/' -def test_http_client_response(): - # Create a core request - request = HttpRequest("GET", "www.httpbin.org") - - # Fake a transport based on http.client - conn = HTTPConnection("www.httpbin.org") - conn.request("GET", "/get") - r1 = conn.getresponse() - - response = HttpClientTransportResponse(request, r1) - - # Don't assume too much in those assert, since we reach a real server - assert response.internal_response is r1 - assert response.reason is not None - assert isinstance(response.status_code, int) - assert len(response.headers.keys()) != 0 - assert len(response.text()) != 0 - assert "content-type" in response.headers - assert "Content-Type" in response.headers - - def test_response_deserialization(): # Method + Url @@ -1108,36 +1087,6 @@ def test_close_unopened_transport(): transport = RequestsTransport() transport.close() -def test_timeout(caplog): - transport = RequestsTransport() - - request = HttpRequest("GET", "https://www.bing.com") - - with caplog.at_level(logging.WARNING, logger="azure.core.pipeline.transport"): - with Pipeline(transport) as pipeline: - pipeline.run(request, connection_timeout=100) - - assert "Tuple timeout setting is deprecated" not in caplog.text - -def test_tuple_timeout(caplog): - transport = RequestsTransport() - - request = HttpRequest("GET", "https://www.bing.com") - - with caplog.at_level(logging.WARNING, logger="azure.core.pipeline.transport"): - with Pipeline(transport) as pipeline: - pipeline.run(request, connection_timeout=(100, 100)) - - assert "Tuple timeout setting is deprecated" in caplog.text - -def test_conflict_timeout(caplog): - transport = RequestsTransport() - - request = HttpRequest("GET", "https://www.bing.com") - - with pytest.raises(ValueError): - with Pipeline(transport) as pipeline: - pipeline.run(request, connection_timeout=(100, 100), read_timeout = 100) @pytest.mark.skipif(sys.version_info < (3, 10), reason="Loop parameter is deprecated since Python 3.10") def test_aiohttp_loop(): diff --git a/sdk/core/azure-core/tests/test_custom_hook_policy.py b/sdk/core/azure-core/tests/test_custom_hook_policy.py index 3103025bd349..6896264a2dd4 100644 --- a/sdk/core/azure-core/tests/test_custom_hook_policy.py +++ b/sdk/core/azure-core/tests/test_custom_hook_policy.py @@ -3,9 +3,13 @@ # Licensed under the MIT License. # ------------------------------------ """Tests for the custom hook policy.""" +try: + from unittest import mock +except ImportError: + import mock from azure.core import PipelineClient from azure.core.pipeline.policies import CustomHookPolicy, UserAgentPolicy -from azure.core.pipeline.transport import HttpRequest +from azure.core.pipeline.transport import HttpRequest, HttpTransport from azure.core.pipeline import PipelineRequest, PipelineContext import pytest @@ -13,13 +17,14 @@ def test_response_hook_policy_in_init(): def test_callback(response): raise ValueError() - url = "https://bing.com" + transport = mock.MagicMock(spec=HttpTransport) + url = "http://127.0.0.1" custom_hook_policy = CustomHookPolicy(raw_response_hook=test_callback) policies = [ UserAgentPolicy("myuseragent"), custom_hook_policy ] - client = PipelineClient(base_url=url, policies=policies) + client = PipelineClient(base_url=url, policies=policies, transport=transport) request = client.get(url) with pytest.raises(ValueError): client._pipeline.run(request) @@ -28,13 +33,14 @@ def test_response_hook_policy_in_request(): def test_callback(response): raise ValueError() - url = "https://bing.com" + transport = mock.MagicMock(spec=HttpTransport) + url = "http://127.0.0.1" custom_hook_policy = CustomHookPolicy() policies = [ UserAgentPolicy("myuseragent"), custom_hook_policy ] - client = PipelineClient(base_url=url, policies=policies) + client = PipelineClient(base_url=url, policies=policies, transport=transport) request = client.get(url) with pytest.raises(ValueError): client._pipeline.run(request, raw_response_hook=test_callback) @@ -46,13 +52,14 @@ def test_callback(response): def test_callback_request(response): raise TypeError() - url = "https://bing.com" + transport = mock.MagicMock(spec=HttpTransport) + url = "http://127.0.0.1" custom_hook_policy = CustomHookPolicy(raw_response_hook=test_callback) policies = [ UserAgentPolicy("myuseragent"), custom_hook_policy ] - client = PipelineClient(base_url=url, policies=policies) + client = PipelineClient(base_url=url, policies=policies, transport=transport) request = client.get(url) with pytest.raises(TypeError): client._pipeline.run(request, raw_response_hook=test_callback_request) @@ -61,13 +68,14 @@ def test_request_hook_policy_in_init(): def test_callback(response): raise ValueError() - url = "https://bing.com" + transport = mock.MagicMock(spec=HttpTransport) + url = "http://127.0.0.1" custom_hook_policy = CustomHookPolicy(raw_request_hook=test_callback) policies = [ UserAgentPolicy("myuseragent"), custom_hook_policy ] - client = PipelineClient(base_url=url, policies=policies) + client = PipelineClient(base_url=url, policies=policies, transport=transport) request = client.get(url) with pytest.raises(ValueError): client._pipeline.run(request) @@ -76,13 +84,14 @@ def test_request_hook_policy_in_request(): def test_callback(response): raise ValueError() - url = "https://bing.com" + transport = mock.MagicMock(spec=HttpTransport) + url = "http://127.0.0.1" custom_hook_policy = CustomHookPolicy() policies = [ UserAgentPolicy("myuseragent"), custom_hook_policy ] - client = PipelineClient(base_url=url, policies=policies) + client = PipelineClient(base_url=url, policies=policies, transport=transport) request = client.get(url) with pytest.raises(ValueError): client._pipeline.run(request, raw_request_hook=test_callback) @@ -94,13 +103,14 @@ def test_callback(response): def test_callback_request(response): raise TypeError() - url = "https://bing.com" + transport = mock.MagicMock(spec=HttpTransport) + url = "http://127.0.0.1" custom_hook_policy = CustomHookPolicy(raw_request_hook=test_callback) policies = [ UserAgentPolicy("myuseragent"), custom_hook_policy ] - client = PipelineClient(base_url=url, policies=policies) + client = PipelineClient(base_url=url, policies=policies, transport=transport) request = client.get(url) with pytest.raises(TypeError): client._pipeline.run(request, raw_request_hook=test_callback_request) diff --git a/sdk/core/azure-core/tests/test_exceptions.py b/sdk/core/azure-core/tests/test_exceptions.py index 399c559cf944..ed42826a6dbd 100644 --- a/sdk/core/azure-core/tests/test_exceptions.py +++ b/sdk/core/azure-core/tests/test_exceptions.py @@ -159,17 +159,6 @@ def test_deserialized_httpresponse_error_message(self): assert isinstance(error.model, FakeErrorTwo) assert isinstance(error.error, ODataV4Format) - def test_httpresponse_error_with_response(self): - response = requests.get("https://bing.com") - http_response = RequestsTransportResponse(None, response) - - error = HttpResponseError(response=http_response) - assert error.message == "Operation returned an invalid status 'OK'" - assert error.response is not None - assert error.reason == 'OK' - assert isinstance(error.status_code, int) - assert error.error is None - def test_odata_v4_exception(self): message = { "error": { diff --git a/sdk/core/azure-core/tests/test_requests_universal.py b/sdk/core/azure-core/tests/test_requests_universal.py index 5a0f778a6b10..2acc0716a57f 100644 --- a/sdk/core/azure-core/tests/test_requests_universal.py +++ b/sdk/core/azure-core/tests/test_requests_universal.py @@ -46,12 +46,6 @@ def thread_body(local_sender): future = executor.submit(thread_body, sender) assert future.result() -def test_requests_auto_headers(): - request = HttpRequest("POST", "https://www.bing.com/") - with RequestsTransport() as sender: - response = sender.send(request) - auto_headers = response.internal_response.request.headers - assert 'Content-Type' not in auto_headers def _create_requests_response(body_bytes, headers=None): # https://github.com/psf/requests/blob/67a7b2e8336951d527e223429672354989384197/requests/adapters.py#L255 diff --git a/sdk/core/azure-core/tests/test_retry_policy.py b/sdk/core/azure-core/tests/test_retry_policy.py index 9980b5367ee2..10c3acb2520a 100644 --- a/sdk/core/azure-core/tests/test_retry_policy.py +++ b/sdk/core/azure-core/tests/test_retry_policy.py @@ -65,7 +65,7 @@ def test_retry_types(): @pytest.mark.parametrize("retry_after_input", [('0'), ('800'), ('1000'), ('1200')]) def test_retry_after(retry_after_input): retry_policy = RetryPolicy() - request = HttpRequest("GET", "https://bing.com") + request = HttpRequest("GET", "http://127.0.0.1") response = HttpResponse(request, None) response.headers["retry-after-ms"] = retry_after_input pipeline_response = PipelineResponse(request, response, None) @@ -83,7 +83,7 @@ def test_retry_after(retry_after_input): @pytest.mark.parametrize("retry_after_input", [('0'), ('800'), ('1000'), ('1200')]) def test_x_ms_retry_after(retry_after_input): retry_policy = RetryPolicy() - request = HttpRequest("GET", "https://bing.com") + request = HttpRequest("GET", "http://127.0.0.1") response = HttpResponse(request, None) response.headers["x-ms-retry-after-ms"] = retry_after_input pipeline_response = PipelineResponse(request, response, None) diff --git a/sdk/core/azure-core/tests/test_tracing_decorator.py b/sdk/core/azure-core/tests/test_tracing_decorator.py index b4a7d3918a8f..01c0c39d4ee7 100644 --- a/sdk/core/azure-core/tests/test_tracing_decorator.py +++ b/sdk/core/azure-core/tests/test_tracing_decorator.py @@ -31,7 +31,7 @@ class MockClient: @distributed_trace def __init__(self, policies=None, assert_current_span=False): time.sleep(0.001) - self.request = HttpRequest("GET", "https://bing.com") + self.request = HttpRequest("GET", "http://127.0.0.1") if policies is None: policies = [] policies.append(mock.Mock(spec=HTTPPolicy, send=self.verify_request)) diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_basic_transport_async_test_server.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_basic_transport_async_test_server.py new file mode 100644 index 000000000000..3ea3c9f85b14 --- /dev/null +++ b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_basic_transport_async_test_server.py @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See LICENSE.txt in the project root for +# license information. +# ------------------------------------------------------------------------- +from six.moves.http_client import HTTPConnection +import time + +try: + from unittest import mock +except ImportError: + import mock + +from azure.core.pipeline.transport import HttpRequest, AioHttpTransport +from azure.core.pipeline import AsyncPipeline + +import pytest + +@pytest.mark.asyncio +async def test_basic_options_aiohttp(port): + + request = HttpRequest("OPTIONS", "http://localhost:{}/basic/string".format(port)) + async with AsyncPipeline(AioHttpTransport(), policies=[]) as pipeline: + response = await pipeline.run(request) + + assert pipeline._transport.session is None + assert isinstance(response.http_response.status_code, int) diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_pipeline_async_test_server.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_pipeline_async_test_server.py new file mode 100644 index 000000000000..6cb902807b15 --- /dev/null +++ b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_pipeline_async_test_server.py @@ -0,0 +1,132 @@ +#-------------------------------------------------------------------------- +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the ""Software""), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +#-------------------------------------------------------------------------- +import sys + +from azure.core.pipeline import AsyncPipeline +from azure.core.pipeline.policies import ( + SansIOHTTPPolicy, + UserAgentPolicy, + DistributedTracingPolicy, + AsyncRetryPolicy, + AsyncRedirectPolicy, + AsyncHTTPPolicy, + AsyncRetryPolicy, + HttpLoggingPolicy, +) +from azure.core.pipeline.transport import ( + AsyncHttpTransport, + HttpRequest, + AsyncioRequestsTransport, + TrioRequestsTransport, + AioHttpTransport +) + +from azure.core.polling.async_base_polling import AsyncLROBasePolling +from azure.core.polling.base_polling import LocationPolling + +from azure.core.configuration import Configuration +from azure.core import AsyncPipelineClient +from azure.core.exceptions import AzureError + +import aiohttp +import trio + +import pytest + + +@pytest.mark.asyncio +async def test_basic_aiohttp(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + async with AsyncPipeline(AioHttpTransport(), policies=policies) as pipeline: + response = await pipeline.run(request) + + assert pipeline._transport.session is None + # all we need to check is if we are able to make the call + assert isinstance(response.http_response.status_code, int) + +@pytest.mark.asyncio +async def test_basic_aiohttp_separate_session(port): + + session = aiohttp.ClientSession() + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + transport = AioHttpTransport(session=session, session_owner=False) + async with AsyncPipeline(transport, policies=policies) as pipeline: + response = await pipeline.run(request) + + assert transport.session + assert isinstance(response.http_response.status_code, int) + await transport.close() + assert transport.session + await transport.session.close() + +@pytest.mark.asyncio +async def test_basic_async_requests(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + async with AsyncPipeline(AsyncioRequestsTransport(), policies=policies) as pipeline: + response = await pipeline.run(request) + + assert isinstance(response.http_response.status_code, int) + +@pytest.mark.asyncio +async def test_conf_async_requests(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + async with AsyncPipeline(AsyncioRequestsTransport(), policies=policies) as pipeline: + response = await pipeline.run(request) + + assert isinstance(response.http_response.status_code, int) + +def test_conf_async_trio_requests(port): + + async def do(): + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + async with AsyncPipeline(TrioRequestsTransport(), policies=policies) as pipeline: + return await pipeline.run(request) + + response = trio.run(do) + assert isinstance(response.http_response.status_code, int) diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_universal_http_async_test_server.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_universal_http_async_test_server.py new file mode 100644 index 000000000000..cde684dba540 --- /dev/null +++ b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_universal_http_async_test_server.py @@ -0,0 +1,91 @@ +#-------------------------------------------------------------------------- +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the ""Software""), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +#-------------------------------------------------------------------------- +import sys + +from azure.core.pipeline.transport import ( + HttpRequest, + AioHttpTransport, + AioHttpTransportResponse, + AsyncHttpTransport, + AsyncioRequestsTransport, + TrioRequestsTransport) + +import aiohttp +import trio + +import pytest + + +@pytest.mark.asyncio +async def test_basic_aiohttp(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + async with AioHttpTransport() as sender: + response = await sender.send(request) + assert response.body() is not None + + assert sender.session is None + assert isinstance(response.status_code, int) + +@pytest.mark.asyncio +async def test_aiohttp_auto_headers(port): + + request = HttpRequest("POST", "http://localhost:{}/basic/string".format(port)) + async with AioHttpTransport() as sender: + response = await sender.send(request) + auto_headers = response.internal_response.request_info.headers + assert 'Content-Type' not in auto_headers + +@pytest.mark.asyncio +async def test_basic_async_requests(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + async with AsyncioRequestsTransport() as sender: + response = await sender.send(request) + assert response.body() is not None + + assert isinstance(response.status_code, int) + +@pytest.mark.asyncio +async def test_conf_async_requests(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + async with AsyncioRequestsTransport() as sender: + response = await sender.send(request) + assert response.body() is not None + + assert isinstance(response.status_code, int) + +def test_conf_async_trio_requests(port): + + async def do(): + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + async with TrioRequestsTransport() as sender: + return await sender.send(request) + assert response.body() is not None + + response = trio.run(do) + assert isinstance(response.status_code, int) diff --git a/sdk/core/azure-core/tests/testserver_tests/test_basic_transport_test_server.py b/sdk/core/azure-core/tests/testserver_tests/test_basic_transport_test_server.py new file mode 100644 index 000000000000..cb74af191ea5 --- /dev/null +++ b/sdk/core/azure-core/tests/testserver_tests/test_basic_transport_test_server.py @@ -0,0 +1,66 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See LICENSE.txt in the project root for +# license information. +# ------------------------------------------------------------------------- +from six.moves.http_client import HTTPConnection +from azure.core.pipeline.transport import HttpRequest, RequestsTransport +from azure.core.pipeline.transport._base import HttpClientTransportResponse +from azure.core.pipeline import Pipeline +import logging +import pytest + + +def test_http_client_response(port): + # Create a core request + request = HttpRequest("GET", "http://localhost:{}".format(port)) + + # Fake a transport based on http.client + conn = HTTPConnection("localhost", port) + conn.request("GET", "/get") + r1 = conn.getresponse() + + response = HttpClientTransportResponse(request, r1) + + # Don't assume too much in those assert, since we reach a real server + assert response.internal_response is r1 + assert response.reason is not None + assert isinstance(response.status_code, int) + assert len(response.headers.keys()) != 0 + assert len(response.text()) != 0 + assert "content-type" in response.headers + assert "Content-Type" in response.headers + + +def test_timeout(caplog, port): + transport = RequestsTransport() + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + + with caplog.at_level(logging.WARNING, logger="azure.core.pipeline.transport"): + with Pipeline(transport) as pipeline: + pipeline.run(request, connection_timeout=100) + + assert "Tuple timeout setting is deprecated" not in caplog.text + + +def test_tuple_timeout(caplog, port): + transport = RequestsTransport() + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + + with caplog.at_level(logging.WARNING, logger="azure.core.pipeline.transport"): + with Pipeline(transport) as pipeline: + pipeline.run(request, connection_timeout=(100, 100)) + + assert "Tuple timeout setting is deprecated" in caplog.text + + +def test_conflict_timeout(caplog, port): + transport = RequestsTransport() + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + + with pytest.raises(ValueError): + with Pipeline(transport) as pipeline: + pipeline.run(request, connection_timeout=(100, 100), read_timeout = 100) diff --git a/sdk/core/azure-core/tests/testserver_tests/test_exceptions_test_server.py b/sdk/core/azure-core/tests/testserver_tests/test_exceptions_test_server.py new file mode 100644 index 000000000000..6dd95c47f90c --- /dev/null +++ b/sdk/core/azure-core/tests/testserver_tests/test_exceptions_test_server.py @@ -0,0 +1,40 @@ +# -------------------------------------------------------------------------- +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the ""Software""), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# -------------------------------------------------------------------------- +import requests +from azure.core.exceptions import HttpResponseError +from azure.core.pipeline.transport import RequestsTransportResponse + +class TestExceptions(object): + def test_httpresponse_error_with_response(self, port): + response = requests.get("http://localhost:{}/basic/string".format(port)) + http_response = RequestsTransportResponse(None, response) + + error = HttpResponseError(response=http_response) + assert error.message == "Operation returned an invalid status 'OK'" + assert error.response is not None + assert error.reason == 'OK' + assert isinstance(error.status_code, int) + assert error.error is None diff --git a/sdk/core/azure-core/tests/testserver_tests/test_requests_universal_test_server.py b/sdk/core/azure-core/tests/testserver_tests/test_requests_universal_test_server.py new file mode 100644 index 000000000000..85f0e955a0e0 --- /dev/null +++ b/sdk/core/azure-core/tests/testserver_tests/test_requests_universal_test_server.py @@ -0,0 +1,33 @@ +# -------------------------------------------------------------------------- +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the ""Software""), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# -------------------------------------------------------------------------- +from azure.core.pipeline.transport import HttpRequest, RequestsTransport + +def test_requests_auto_headers(port): + request = HttpRequest("POST", "http://localhost:{}/basic/string".format(port)) + with RequestsTransport() as sender: + response = sender.send(request) + auto_headers = response.internal_response.request.headers + assert 'Content-Type' not in auto_headers From 8b67d10d6678c3fc5cf245c8d40bd1b5ba69900b Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Mon, 2 Aug 2021 11:10:22 -0700 Subject: [PATCH 2/6] clean up --- .../azure-core/tests/test_base_polling.py | 3 - .../azure-core/tests/test_basic_transport.py | 6 +- .../tests/test_connection_string_parsing.py | 1 - .../tests/test_custom_hook_policy.py | 3 +- sdk/core/azure-core/tests/test_exceptions.py | 6 - .../tests/test_messaging_cloud_event.py | 1 - sdk/core/azure-core/tests/test_pipeline.py | 558 ++++++++---------- sdk/core/azure-core/tests/test_polling.py | 2 - .../tests/test_requests_universal.py | 3 +- sdk/core/azure-core/tests/test_streaming.py | 1 - .../tests/test_tracing_decorator.py | 1 - .../azure-core/tests/test_tracing_policy.py | 1 - .../tests/test_universal_pipeline.py | 2 - .../test_basic_transport_async_test_server.py | 5 - .../test_pipeline_async_test_server.py | 14 - .../test_universal_http_async_test_server.py | 6 +- .../test_pipeline_test_server.py | 105 ++++ 17 files changed, 348 insertions(+), 370 deletions(-) create mode 100644 sdk/core/azure-core/tests/testserver_tests/test_pipeline_test_server.py diff --git a/sdk/core/azure-core/tests/test_base_polling.py b/sdk/core/azure-core/tests/test_base_polling.py index 5ad08aa2334a..f5c1db343302 100644 --- a/sdk/core/azure-core/tests/test_base_polling.py +++ b/sdk/core/azure-core/tests/test_base_polling.py @@ -30,7 +30,6 @@ import types import pickle import platform -import unittest import six try: from unittest import mock @@ -41,8 +40,6 @@ from requests import Request, Response -from msrest import Deserializer - from azure.core.polling import LROPoller from azure.core.exceptions import DecodeError, HttpResponseError from azure.core import PipelineClient diff --git a/sdk/core/azure-core/tests/test_basic_transport.py b/sdk/core/azure-core/tests/test_basic_transport.py index d7c08e5ae601..0f3c9f754b4d 100644 --- a/sdk/core/azure-core/tests/test_basic_transport.py +++ b/sdk/core/azure-core/tests/test_basic_transport.py @@ -3,11 +3,8 @@ # Licensed under the MIT License. See LICENSE.txt in the project root for # license information. # ------------------------------------------------------------------------- -from six.moves.http_client import HTTPConnection from collections import OrderedDict -import time import sys -import json try: from unittest import mock @@ -15,11 +12,10 @@ import mock from azure.core.pipeline.transport import HttpRequest, HttpResponse, RequestsTransport -from azure.core.pipeline.transport._base import HttpClientTransportResponse, HttpTransport, _deserialize_response, _urljoin +from azure.core.pipeline.transport._base import HttpTransport, _deserialize_response, _urljoin from azure.core.pipeline.policies import HeadersPolicy from azure.core.pipeline import Pipeline from azure.core.exceptions import HttpResponseError -import logging import pytest diff --git a/sdk/core/azure-core/tests/test_connection_string_parsing.py b/sdk/core/azure-core/tests/test_connection_string_parsing.py index 1decf6ce45a5..fe194c7766f4 100644 --- a/sdk/core/azure-core/tests/test_connection_string_parsing.py +++ b/sdk/core/azure-core/tests/test_connection_string_parsing.py @@ -1,4 +1,3 @@ -import sys import pytest from azure.core.utils import parse_connection_string diff --git a/sdk/core/azure-core/tests/test_custom_hook_policy.py b/sdk/core/azure-core/tests/test_custom_hook_policy.py index 6896264a2dd4..ce4e9638a7cf 100644 --- a/sdk/core/azure-core/tests/test_custom_hook_policy.py +++ b/sdk/core/azure-core/tests/test_custom_hook_policy.py @@ -9,8 +9,7 @@ import mock from azure.core import PipelineClient from azure.core.pipeline.policies import CustomHookPolicy, UserAgentPolicy -from azure.core.pipeline.transport import HttpRequest, HttpTransport -from azure.core.pipeline import PipelineRequest, PipelineContext +from azure.core.pipeline.transport import HttpTransport import pytest def test_response_hook_policy_in_init(): diff --git a/sdk/core/azure-core/tests/test_exceptions.py b/sdk/core/azure-core/tests/test_exceptions.py index ed42826a6dbd..7b2bf3ee76d8 100644 --- a/sdk/core/azure-core/tests/test_exceptions.py +++ b/sdk/core/azure-core/tests/test_exceptions.py @@ -24,11 +24,6 @@ # # -------------------------------------------------------------------------- import json -import logging -import os - -import requests -import pytest try: from unittest.mock import Mock except ImportError: @@ -37,7 +32,6 @@ # module under test from azure.core.exceptions import HttpResponseError, ODataV4Error, ODataV4Format -from azure.core.pipeline.transport import RequestsTransportResponse from azure.core.pipeline.transport._base import _HttpResponseBase diff --git a/sdk/core/azure-core/tests/test_messaging_cloud_event.py b/sdk/core/azure-core/tests/test_messaging_cloud_event.py index c2d76b5a002c..9974d4908a42 100644 --- a/sdk/core/azure-core/tests/test_messaging_cloud_event.py +++ b/sdk/core/azure-core/tests/test_messaging_cloud_event.py @@ -3,7 +3,6 @@ # Licensed under the MIT License. # ------------------------------------ import pytest -import json import datetime from azure.core.messaging import CloudEvent diff --git a/sdk/core/azure-core/tests/test_pipeline.py b/sdk/core/azure-core/tests/test_pipeline.py index f4bbfc6636c3..e056d18350ee 100644 --- a/sdk/core/azure-core/tests/test_pipeline.py +++ b/sdk/core/azure-core/tests/test_pipeline.py @@ -26,22 +26,13 @@ import json import requests -import datetime -from enum import Enum -import unittest try: from io import BytesIO except ImportError: from cStringIO import StringIO as BytesIO - -try: - from unittest import mock -except ImportError: - import mock import xml.etree.ElementTree as ET import sys -import requests import pytest from azure.core.configuration import Configuration @@ -117,322 +108,249 @@ def on_exception(self, requests, **kwargs): with pytest.raises(NotImplementedError): pipeline.run(req) -class TestRequestsTransport(unittest.TestCase): +def test_requests_socket_timeout(): + conf = Configuration() + request = HttpRequest("GET", "https://bing.com") + policies = [ + UserAgentPolicy("myusergant"), + RedirectPolicy() + ] + # Sometimes this will raise a read timeout, sometimes a socket timeout depending on timing. + # Either way, the error should always be wrapped as an AzureError to ensure it's caught + # by the retry policy. + with pytest.raises(AzureError): + with Pipeline(RequestsTransport(), policies=policies) as pipeline: + response = pipeline.run(request, connection_timeout=0.000001, read_timeout=0.000001) + +def test_format_url_basic(): + client = PipelineClientBase("https://bing.com") + formatted = client.format_url("/{foo}", foo="bar") + assert formatted == "https://bing.com/bar" - def test_basic_requests(self): +def test_format_url_with_query(): + client = PipelineClientBase("https://bing.com/path?query=testvalue&x=2ndvalue") + formatted = client.format_url("/{foo}", foo="bar") + assert formatted == "https://bing.com/path/bar?query=testvalue&x=2ndvalue" - conf = Configuration() - request = HttpRequest("GET", "https://bing.com") - policies = [ - UserAgentPolicy("myusergant"), - RedirectPolicy() - ] - with Pipeline(RequestsTransport(), policies=policies) as pipeline: - response = pipeline.run(request) +def test_format_url_missing_param_values(): + client = PipelineClientBase("https://bing.com/path") + formatted = client.format_url("/{foo}") + assert formatted == "https://bing.com/path" - assert pipeline._transport.session is None - assert isinstance(response.http_response.status_code, int) +def test_format_url_missing_param_values_with_query(): + client = PipelineClientBase("https://bing.com/path?query=testvalue&x=2ndvalue") + formatted = client.format_url("/{foo}") + assert formatted == "https://bing.com/path?query=testvalue&x=2ndvalue" - def test_basic_options_requests(self): +def test_format_url_extra_path(): + client = PipelineClientBase("https://bing.com/path") + formatted = client.format_url("/subpath/{foo}", foo="bar") + assert formatted == "https://bing.com/path/subpath/bar" - request = HttpRequest("OPTIONS", "https://httpbin.org") - policies = [ - UserAgentPolicy("myusergant"), - RedirectPolicy() - ] - with Pipeline(RequestsTransport(), policies=policies) as pipeline: - response = pipeline.run(request) - - assert pipeline._transport.session is None - assert isinstance(response.http_response.status_code, int) - - def test_requests_socket_timeout(self): - conf = Configuration() - request = HttpRequest("GET", "https://bing.com") - policies = [ - UserAgentPolicy("myusergant"), - RedirectPolicy() - ] - # Sometimes this will raise a read timeout, sometimes a socket timeout depending on timing. - # Either way, the error should always be wrapped as an AzureError to ensure it's caught - # by the retry policy. - with pytest.raises(AzureError): - with Pipeline(RequestsTransport(), policies=policies) as pipeline: - response = pipeline.run(request, connection_timeout=0.000001, read_timeout=0.000001) - - def test_basic_requests_separate_session(self): - - session = requests.Session() - request = HttpRequest("GET", "https://bing.com") - policies = [ - UserAgentPolicy("myusergant"), - RedirectPolicy() - ] - transport = RequestsTransport(session=session, session_owner=False) - with Pipeline(transport, policies=policies) as pipeline: - response = pipeline.run(request) - - assert transport.session - assert isinstance(response.http_response.status_code, int) - transport.close() - assert transport.session - transport.session.close() - -class TestClientPipelineURLFormatting(unittest.TestCase): - - def test_format_url_basic(self): - client = PipelineClientBase("https://bing.com") - formatted = client.format_url("/{foo}", foo="bar") - assert formatted == "https://bing.com/bar" - - def test_format_url_with_query(self): - client = PipelineClientBase("https://bing.com/path?query=testvalue&x=2ndvalue") - formatted = client.format_url("/{foo}", foo="bar") - assert formatted == "https://bing.com/path/bar?query=testvalue&x=2ndvalue" - - def test_format_url_missing_param_values(self): - client = PipelineClientBase("https://bing.com/path") - formatted = client.format_url("/{foo}") - assert formatted == "https://bing.com/path" - - def test_format_url_missing_param_values_with_query(self): - client = PipelineClientBase("https://bing.com/path?query=testvalue&x=2ndvalue") - formatted = client.format_url("/{foo}") - assert formatted == "https://bing.com/path?query=testvalue&x=2ndvalue" - - def test_format_url_extra_path(self): - client = PipelineClientBase("https://bing.com/path") - formatted = client.format_url("/subpath/{foo}", foo="bar") - assert formatted == "https://bing.com/path/subpath/bar" - - def test_format_url_complex_params(self): - client = PipelineClientBase("https://bing.com/path") - formatted = client.format_url("/subpath/{a}/{b}/foo/{c}/bar", a="X", c="Y") - assert formatted == "https://bing.com/path/subpath/X/foo/Y/bar" - - def test_format_url_extra_path_missing_values(self): - client = PipelineClientBase("https://bing.com/path") - formatted = client.format_url("/subpath/{foo}") - assert formatted == "https://bing.com/path/subpath" - - def test_format_url_extra_path_missing_values_with_query(self): - client = PipelineClientBase("https://bing.com/path?query=testvalue&x=2ndvalue") - formatted = client.format_url("/subpath/{foo}") - assert formatted == "https://bing.com/path/subpath?query=testvalue&x=2ndvalue" - - def test_format_url_full_url(self): - client = PipelineClientBase("https://bing.com/path") - formatted = client.format_url("https://google.com/subpath/{foo}", foo="bar") - assert formatted == "https://google.com/subpath/bar" - - def test_format_url_no_base_url(self): - client = PipelineClientBase(None) - formatted = client.format_url("https://google.com/subpath/{foo}", foo="bar") - assert formatted == "https://google.com/subpath/bar" - - def test_format_incorrect_endpoint(self): - # https://github.com/Azure/azure-sdk-for-python/pull/12106 - client = PipelineClientBase('{Endpoint}/text/analytics/v3.0') - with pytest.raises(ValueError) as exp: - client.format_url("foo/bar") - assert str(exp.value) == "The value provided for the url part Endpoint was incorrect, and resulted in an invalid url" - -class TestClientRequest(unittest.TestCase): - def test_request_json(self): - - request = HttpRequest("GET", "/") - data = "Lots of dataaaa" - request.set_json_body(data) - - self.assertEqual(request.data, json.dumps(data)) - self.assertEqual(request.headers.get("Content-Length"), "17") - - def test_request_data(self): - - request = HttpRequest("GET", "/") - data = "Lots of dataaaa" - request.set_bytes_body(data) - - self.assertEqual(request.data, data) - self.assertEqual(request.headers.get("Content-Length"), "15") - - def test_request_stream(self): - request = HttpRequest("GET", "/") - - data = b"Lots of dataaaa" - request.set_streamed_data_body(data) - self.assertEqual(request.data, data) - - def data_gen(): - for i in range(10): - yield i - data = data_gen() - request.set_streamed_data_body(data) - self.assertEqual(request.data, data) - - data = BytesIO(b"Lots of dataaaa") - request.set_streamed_data_body(data) - self.assertEqual(request.data, data) - - - def test_request_xml(self): - request = HttpRequest("GET", "/") - data = ET.Element("root") - request.set_xml_body(data) - - assert request.data == b"\n" - - def test_request_url_with_params(self): - - request = HttpRequest("GET", "/") - request.url = "a/b/c?t=y" - request.format_parameters({"g": "h"}) - - self.assertIn(request.url, ["a/b/c?g=h&t=y", "a/b/c?t=y&g=h"]) - - def test_request_url_with_params_as_list(self): - - request = HttpRequest("GET", "/") - request.url = "a/b/c?t=y" - request.format_parameters({"g": ["h","i"]}) - - self.assertIn(request.url, ["a/b/c?g=h&g=i&t=y", "a/b/c?t=y&g=h&g=i"]) - - def test_request_url_with_params_with_none_in_list(self): - - request = HttpRequest("GET", "/") - request.url = "a/b/c?t=y" - with pytest.raises(ValueError): - request.format_parameters({"g": ["h",None]}) - - def test_request_url_with_params_with_none(self): - - request = HttpRequest("GET", "/") - request.url = "a/b/c?t=y" - with pytest.raises(ValueError): - request.format_parameters({"g": None}) - - - def test_request_text(self): - client = PipelineClientBase('http://example.org') - request = client.get( - "/", - content="foo" - ) - - # In absence of information, everything is JSON (double quote added) - assert request.data == json.dumps("foo") - - request = client.post( - "/", - headers={'content-type': 'text/whatever'}, - content="foo" - ) - - # We want a direct string - assert request.data == "foo" - - def test_repr(self): - request = HttpRequest("GET", "hello.com") - assert repr(request) == "" - - def test_add_custom_policy(self): - class BooPolicy(HTTPPolicy): - def send(*args): - raise AzureError('boo') - - class FooPolicy(HTTPPolicy): - def send(*args): - raise AzureError('boo') - - config = Configuration() - retry_policy = RetryPolicy() - config.retry_policy = retry_policy - boo_policy = BooPolicy() - foo_policy = FooPolicy() - client = PipelineClient(base_url="test", config=config, per_call_policies=boo_policy) - policies = client._pipeline._impl_policies - assert boo_policy in policies - pos_boo = policies.index(boo_policy) - pos_retry = policies.index(retry_policy) - assert pos_boo < pos_retry - - client = PipelineClient(base_url="test", config=config, per_call_policies=[boo_policy]) - policies = client._pipeline._impl_policies - assert boo_policy in policies - pos_boo = policies.index(boo_policy) - pos_retry = policies.index(retry_policy) - assert pos_boo < pos_retry - - client = PipelineClient(base_url="test", config=config, per_retry_policies=boo_policy) - policies = client._pipeline._impl_policies - assert boo_policy in policies - pos_boo = policies.index(boo_policy) - pos_retry = policies.index(retry_policy) - assert pos_boo > pos_retry - - client = PipelineClient(base_url="test", config=config, per_retry_policies=[boo_policy]) - policies = client._pipeline._impl_policies - assert boo_policy in policies - pos_boo = policies.index(boo_policy) - pos_retry = policies.index(retry_policy) - assert pos_boo > pos_retry - - client = PipelineClient(base_url="test", config=config, per_call_policies=boo_policy, per_retry_policies=foo_policy) - policies = client._pipeline._impl_policies - assert boo_policy in policies - assert foo_policy in policies - pos_boo = policies.index(boo_policy) - pos_foo = policies.index(foo_policy) - pos_retry = policies.index(retry_policy) - assert pos_boo < pos_retry - assert pos_foo > pos_retry - - client = PipelineClient(base_url="test", config=config, per_call_policies=[boo_policy], - per_retry_policies=[foo_policy]) - policies = client._pipeline._impl_policies - assert boo_policy in policies - assert foo_policy in policies - pos_boo = policies.index(boo_policy) - pos_foo = policies.index(foo_policy) - pos_retry = policies.index(retry_policy) - assert pos_boo < pos_retry - assert pos_foo > pos_retry - - policies = [UserAgentPolicy(), - RetryPolicy(), - DistributedTracingPolicy()] - client = PipelineClient(base_url="test", policies=policies, per_call_policies=boo_policy) - actual_policies = client._pipeline._impl_policies - assert boo_policy == actual_policies[0] - client = PipelineClient(base_url="test", policies=policies, per_call_policies=[boo_policy]) - actual_policies = client._pipeline._impl_policies - assert boo_policy == actual_policies[0] +def test_format_url_complex_params(): + client = PipelineClientBase("https://bing.com/path") + formatted = client.format_url("/subpath/{a}/{b}/foo/{c}/bar", a="X", c="Y") + assert formatted == "https://bing.com/path/subpath/X/foo/Y/bar" + +def test_format_url_extra_path_missing_values(): + client = PipelineClientBase("https://bing.com/path") + formatted = client.format_url("/subpath/{foo}") + assert formatted == "https://bing.com/path/subpath" + +def test_format_url_extra_path_missing_values_with_query(): + client = PipelineClientBase("https://bing.com/path?query=testvalue&x=2ndvalue") + formatted = client.format_url("/subpath/{foo}") + assert formatted == "https://bing.com/path/subpath?query=testvalue&x=2ndvalue" + +def test_format_url_full_url(): + client = PipelineClientBase("https://bing.com/path") + formatted = client.format_url("https://google.com/subpath/{foo}", foo="bar") + assert formatted == "https://google.com/subpath/bar" + +def test_format_url_no_base_url(): + client = PipelineClientBase(None) + formatted = client.format_url("https://google.com/subpath/{foo}", foo="bar") + assert formatted == "https://google.com/subpath/bar" + +def test_format_incorrect_endpoint(): + # https://github.com/Azure/azure-sdk-for-python/pull/12106 + client = PipelineClientBase('{Endpoint}/text/analytics/v3.0') + with pytest.raises(ValueError) as exp: + client.format_url("foo/bar") + assert str(exp.value) == "The value provided for the url part Endpoint was incorrect, and resulted in an invalid url" + +def test_request_json(): + + request = HttpRequest("GET", "/") + data = "Lots of dataaaa" + request.set_json_body(data) + + assert request.data == json.dumps(data) + assert request.headers.get("Content-Length") == "17" + +def test_request_data(): + + request = HttpRequest("GET", "/") + data = "Lots of dataaaa" + request.set_bytes_body(data) + + assert request.data == data + assert request.headers.get("Content-Length") == "15" + +def test_request_stream(): + request = HttpRequest("GET", "/") + + data = b"Lots of dataaaa" + request.set_streamed_data_body(data) + assert request.data == data + + def data_gen(): + for i in range(10): + yield i + data = data_gen() + request.set_streamed_data_body(data) + assert request.data == data + + data = BytesIO(b"Lots of dataaaa") + request.set_streamed_data_body(data) + assert request.data == data + +def test_request_xml(): + request = HttpRequest("GET", "/") + data = ET.Element("root") + request.set_xml_body(data) + + assert request.data == b"\n" + +def test_request_url_with_params(): + + request = HttpRequest("GET", "/") + request.url = "a/b/c?t=y" + request.format_parameters({"g": "h"}) + + assert request.url in ["a/b/c?g=h&t=y", "a/b/c?t=y&g=h"] + +def test_request_url_with_params_as_list(): + + request = HttpRequest("GET", "/") + request.url = "a/b/c?t=y" + request.format_parameters({"g": ["h","i"]}) + + assert request.url in ["a/b/c?g=h&g=i&t=y", "a/b/c?t=y&g=h&g=i"] + +def test_request_url_with_params_with_none_in_list(): + + request = HttpRequest("GET", "/") + request.url = "a/b/c?t=y" + with pytest.raises(ValueError): + request.format_parameters({"g": ["h",None]}) + +def test_request_url_with_params_with_none(): + + request = HttpRequest("GET", "/") + request.url = "a/b/c?t=y" + with pytest.raises(ValueError): + request.format_parameters({"g": None}) + +def test_repr(): + request = HttpRequest("GET", "hello.com") + assert repr(request) == "" + +def test_add_custom_policy(): + class BooPolicy(HTTPPolicy): + def send(*args): + raise AzureError('boo') + + class FooPolicy(HTTPPolicy): + def send(*args): + raise AzureError('boo') + + config = Configuration() + retry_policy = RetryPolicy() + config.retry_policy = retry_policy + boo_policy = BooPolicy() + foo_policy = FooPolicy() + client = PipelineClient(base_url="test", config=config, per_call_policies=boo_policy) + policies = client._pipeline._impl_policies + assert boo_policy in policies + pos_boo = policies.index(boo_policy) + pos_retry = policies.index(retry_policy) + assert pos_boo < pos_retry + + client = PipelineClient(base_url="test", config=config, per_call_policies=[boo_policy]) + policies = client._pipeline._impl_policies + assert boo_policy in policies + pos_boo = policies.index(boo_policy) + pos_retry = policies.index(retry_policy) + assert pos_boo < pos_retry + + client = PipelineClient(base_url="test", config=config, per_retry_policies=boo_policy) + policies = client._pipeline._impl_policies + assert boo_policy in policies + pos_boo = policies.index(boo_policy) + pos_retry = policies.index(retry_policy) + assert pos_boo > pos_retry + + client = PipelineClient(base_url="test", config=config, per_retry_policies=[boo_policy]) + policies = client._pipeline._impl_policies + assert boo_policy in policies + pos_boo = policies.index(boo_policy) + pos_retry = policies.index(retry_policy) + assert pos_boo > pos_retry + + client = PipelineClient(base_url="test", config=config, per_call_policies=boo_policy, per_retry_policies=foo_policy) + policies = client._pipeline._impl_policies + assert boo_policy in policies + assert foo_policy in policies + pos_boo = policies.index(boo_policy) + pos_foo = policies.index(foo_policy) + pos_retry = policies.index(retry_policy) + assert pos_boo < pos_retry + assert pos_foo > pos_retry + + client = PipelineClient(base_url="test", config=config, per_call_policies=[boo_policy], + per_retry_policies=[foo_policy]) + policies = client._pipeline._impl_policies + assert boo_policy in policies + assert foo_policy in policies + pos_boo = policies.index(boo_policy) + pos_foo = policies.index(foo_policy) + pos_retry = policies.index(retry_policy) + assert pos_boo < pos_retry + assert pos_foo > pos_retry + + policies = [UserAgentPolicy(), + RetryPolicy(), + DistributedTracingPolicy()] + client = PipelineClient(base_url="test", policies=policies, per_call_policies=boo_policy) + actual_policies = client._pipeline._impl_policies + assert boo_policy == actual_policies[0] + client = PipelineClient(base_url="test", policies=policies, per_call_policies=[boo_policy]) + actual_policies = client._pipeline._impl_policies + assert boo_policy == actual_policies[0] + + client = PipelineClient(base_url="test", policies=policies, per_retry_policies=foo_policy) + actual_policies = client._pipeline._impl_policies + assert foo_policy == actual_policies[2] + client = PipelineClient(base_url="test", policies=policies, per_retry_policies=[foo_policy]) + actual_policies = client._pipeline._impl_policies + assert foo_policy == actual_policies[2] + + client = PipelineClient(base_url="test", policies=policies, per_call_policies=boo_policy, + per_retry_policies=foo_policy) + actual_policies = client._pipeline._impl_policies + assert boo_policy == actual_policies[0] + assert foo_policy == actual_policies[3] + client = PipelineClient(base_url="test", policies=policies, per_call_policies=[boo_policy], + per_retry_policies=[foo_policy]) + actual_policies = client._pipeline._impl_policies + assert boo_policy == actual_policies[0] + assert foo_policy == actual_policies[3] + + policies = [UserAgentPolicy(), + DistributedTracingPolicy()] + with pytest.raises(ValueError): client = PipelineClient(base_url="test", policies=policies, per_retry_policies=foo_policy) - actual_policies = client._pipeline._impl_policies - assert foo_policy == actual_policies[2] + with pytest.raises(ValueError): client = PipelineClient(base_url="test", policies=policies, per_retry_policies=[foo_policy]) - actual_policies = client._pipeline._impl_policies - assert foo_policy == actual_policies[2] - - client = PipelineClient(base_url="test", policies=policies, per_call_policies=boo_policy, - per_retry_policies=foo_policy) - actual_policies = client._pipeline._impl_policies - assert boo_policy == actual_policies[0] - assert foo_policy == actual_policies[3] - client = PipelineClient(base_url="test", policies=policies, per_call_policies=[boo_policy], - per_retry_policies=[foo_policy]) - actual_policies = client._pipeline._impl_policies - assert boo_policy == actual_policies[0] - assert foo_policy == actual_policies[3] - - policies = [UserAgentPolicy(), - DistributedTracingPolicy()] - with pytest.raises(ValueError): - client = PipelineClient(base_url="test", policies=policies, per_retry_policies=foo_policy) - with pytest.raises(ValueError): - client = PipelineClient(base_url="test", policies=policies, per_retry_policies=[foo_policy]) - -if __name__ == "__main__": - unittest.main() diff --git a/sdk/core/azure-core/tests/test_polling.py b/sdk/core/azure-core/tests/test_polling.py index 0eda477be5c7..6bdfc4686657 100644 --- a/sdk/core/azure-core/tests/test_polling.py +++ b/sdk/core/azure-core/tests/test_polling.py @@ -39,8 +39,6 @@ LROBasePolling, LocationPolling ) from msrest.serialization import Model -from azure.core.pipeline import PipelineResponse -from azure.core.pipeline.transport import HttpResponse @pytest.fixture diff --git a/sdk/core/azure-core/tests/test_requests_universal.py b/sdk/core/azure-core/tests/test_requests_universal.py index 2acc0716a57f..b599586993ee 100644 --- a/sdk/core/azure-core/tests/test_requests_universal.py +++ b/sdk/core/azure-core/tests/test_requests_universal.py @@ -27,8 +27,7 @@ import pytest import requests.utils -from azure.core.pipeline.transport import HttpRequest, RequestsTransport, RequestsTransportResponse -from azure.core.configuration import Configuration +from azure.core.pipeline.transport import RequestsTransport, RequestsTransportResponse def test_threading_basic_requests(): diff --git a/sdk/core/azure-core/tests/test_streaming.py b/sdk/core/azure-core/tests/test_streaming.py index 26041540159d..2a5e6a4d0bb8 100644 --- a/sdk/core/azure-core/tests/test_streaming.py +++ b/sdk/core/azure-core/tests/test_streaming.py @@ -23,7 +23,6 @@ # THE SOFTWARE. # # -------------------------------------------------------------------------- -import os from azure.core import PipelineClient from azure.core.exceptions import DecodeError diff --git a/sdk/core/azure-core/tests/test_tracing_decorator.py b/sdk/core/azure-core/tests/test_tracing_decorator.py index 01c0c39d4ee7..140e3b0656ac 100644 --- a/sdk/core/azure-core/tests/test_tracing_decorator.py +++ b/sdk/core/azure-core/tests/test_tracing_decorator.py @@ -9,7 +9,6 @@ except ImportError: import mock -import sys import time import pytest diff --git a/sdk/core/azure-core/tests/test_tracing_policy.py b/sdk/core/azure-core/tests/test_tracing_policy.py index c52572d40357..743d2078acb5 100644 --- a/sdk/core/azure-core/tests/test_tracing_policy.py +++ b/sdk/core/azure-core/tests/test_tracing_policy.py @@ -11,7 +11,6 @@ from azure.core.settings import settings from tracing_common import FakeSpan import time -import pytest try: from unittest import mock diff --git a/sdk/core/azure-core/tests/test_universal_pipeline.py b/sdk/core/azure-core/tests/test_universal_pipeline.py index cb181ab5b9b1..b14f63fd7931 100644 --- a/sdk/core/azure-core/tests/test_universal_pipeline.py +++ b/sdk/core/azure-core/tests/test_universal_pipeline.py @@ -50,8 +50,6 @@ from azure.core.pipeline.policies import ( NetworkTraceLoggingPolicy, ContentDecodePolicy, - UserAgentPolicy, - HttpLoggingPolicy, RequestHistory, RetryPolicy, HTTPPolicy, diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_basic_transport_async_test_server.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_basic_transport_async_test_server.py index 3ea3c9f85b14..d96cb4d23ec8 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_basic_transport_async_test_server.py +++ b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_basic_transport_async_test_server.py @@ -6,11 +6,6 @@ from six.moves.http_client import HTTPConnection import time -try: - from unittest import mock -except ImportError: - import mock - from azure.core.pipeline.transport import HttpRequest, AioHttpTransport from azure.core.pipeline import AsyncPipeline diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_pipeline_async_test_server.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_pipeline_async_test_server.py index 6cb902807b15..7304ae90874e 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_pipeline_async_test_server.py +++ b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_pipeline_async_test_server.py @@ -27,30 +27,16 @@ from azure.core.pipeline import AsyncPipeline from azure.core.pipeline.policies import ( - SansIOHTTPPolicy, UserAgentPolicy, - DistributedTracingPolicy, - AsyncRetryPolicy, AsyncRedirectPolicy, - AsyncHTTPPolicy, - AsyncRetryPolicy, - HttpLoggingPolicy, ) from azure.core.pipeline.transport import ( - AsyncHttpTransport, HttpRequest, AsyncioRequestsTransport, TrioRequestsTransport, AioHttpTransport ) -from azure.core.polling.async_base_polling import AsyncLROBasePolling -from azure.core.polling.base_polling import LocationPolling - -from azure.core.configuration import Configuration -from azure.core import AsyncPipelineClient -from azure.core.exceptions import AzureError - import aiohttp import trio diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_universal_http_async_test_server.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_universal_http_async_test_server.py index cde684dba540..d4c376ed3241 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_universal_http_async_test_server.py +++ b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_universal_http_async_test_server.py @@ -28,12 +28,10 @@ from azure.core.pipeline.transport import ( HttpRequest, AioHttpTransport, - AioHttpTransportResponse, - AsyncHttpTransport, AsyncioRequestsTransport, - TrioRequestsTransport) + TrioRequestsTransport +) -import aiohttp import trio import pytest diff --git a/sdk/core/azure-core/tests/testserver_tests/test_pipeline_test_server.py b/sdk/core/azure-core/tests/testserver_tests/test_pipeline_test_server.py new file mode 100644 index 000000000000..d5c503a39fa3 --- /dev/null +++ b/sdk/core/azure-core/tests/testserver_tests/test_pipeline_test_server.py @@ -0,0 +1,105 @@ +# -------------------------------------------------------------------------- +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the ""Software""), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# -------------------------------------------------------------------------- + +import json +import requests + +from azure.core.configuration import Configuration +from azure.core.pipeline import Pipeline +from azure.core.pipeline.policies import ( + UserAgentPolicy, + RedirectPolicy, +) +from azure.core.pipeline.transport._base import PipelineClientBase +from azure.core.pipeline.transport import ( + HttpRequest, + RequestsTransport, +) + + +def test_basic_requests(port): + + conf = Configuration() + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + RedirectPolicy() + ] + with Pipeline(RequestsTransport(), policies=policies) as pipeline: + response = pipeline.run(request) + + assert pipeline._transport.session is None + assert isinstance(response.http_response.status_code, int) + +def test_basic_options_requests(port): + + request = HttpRequest("OPTIONS", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + RedirectPolicy() + ] + with Pipeline(RequestsTransport(), policies=policies) as pipeline: + response = pipeline.run(request) + + assert pipeline._transport.session is None + assert isinstance(response.http_response.status_code, int) + +def test_basic_requests_separate_session(port): + + session = requests.Session() + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + RedirectPolicy() + ] + transport = RequestsTransport(session=session, session_owner=False) + with Pipeline(transport, policies=policies) as pipeline: + response = pipeline.run(request) + + assert transport.session + assert isinstance(response.http_response.status_code, int) + transport.close() + assert transport.session + transport.session.close() + +def test_request_text(port): + client = PipelineClientBase("http://localhost:{}".format(port)) + request = client.get( + "/", + content="foo" + ) + + # In absence of information, everything is JSON (double quote added) + assert request.data == json.dumps("foo") + + request = client.post( + "/", + headers={'content-type': 'text/whatever'}, + content="foo" + ) + + # We want a direct string + assert request.data == "foo" From 2504ecb40261e553bcd669d934789137ab55efb5 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Wed, 11 Aug 2021 14:35:16 -0700 Subject: [PATCH 3/6] use localhost instead of 127.0.0.1 --- .../test_http_logging_policy_async.py | 28 +++++++++---------- .../async_tests/test_retry_policy_async.py | 18 ++++++------ .../test_stream_generator_async.py | 4 +-- .../test_tracing_decorator_async.py | 2 +- .../tests/test_custom_hook_policy.py | 12 ++++---- .../tests/test_http_logging_policy.py | 28 +++++++++---------- .../tests/test_request_id_policy.py | 4 +-- .../azure-core/tests/test_retry_policy.py | 18 ++++++------ .../azure-core/tests/test_stream_generator.py | 4 +-- .../tests/test_tracing_decorator.py | 2 +- .../azure-core/tests/test_tracing_policy.py | 16 +++++------ .../tests/test_universal_pipeline.py | 8 +++--- .../tests/test_user_agent_policy.py | 4 +-- .../test_rest_http_request.py | 6 ++-- 14 files changed, 77 insertions(+), 77 deletions(-) diff --git a/sdk/core/azure-core/tests/async_tests/test_http_logging_policy_async.py b/sdk/core/azure-core/tests/async_tests/test_http_logging_policy_async.py index 13ed07d67af6..0c4e931bc4e2 100644 --- a/sdk/core/azure-core/tests/async_tests/test_http_logging_policy_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_http_logging_policy_async.py @@ -41,7 +41,7 @@ def emit(self, record): policy = HttpLoggingPolicy(logger=logger) - universal_request = HttpRequest('GET', 'http://127.0.0.1/') + universal_request = HttpRequest('GET', 'http://localhost/') http_response = HttpResponse(universal_request, None) http_response.status_code = 202 request = PipelineRequest(universal_request, PipelineContext(None)) @@ -54,7 +54,7 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 6 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == 'Request headers:' assert mock_handler.messages[3].message == 'No body was attached to the request' @@ -75,13 +75,13 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 12 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == 'Request headers:' assert mock_handler.messages[3].message == 'No body was attached to the request' assert mock_handler.messages[4].message == 'Response status: 202' assert mock_handler.messages[5].message == 'Response headers:' - assert mock_handler.messages[6].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[6].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[7].message == "Request method: 'GET'" assert mock_handler.messages[8].message == 'Request headers:' assert mock_handler.messages[9].message == 'No body was attached to the request' @@ -102,7 +102,7 @@ def emit(self, record): "Content-Type": "Caramel", "HateToo": "Chocolat", } - universal_request.url = "http://127.0.0.1/?country=france&city=aix" + universal_request.url = "http://localhost/?country=france&city=aix" policy.on_request(request) response = PipelineResponse(request, http_response, request.context) @@ -110,7 +110,7 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 10 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/?country=france&city=REDACTED'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/?country=france&city=REDACTED'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == "Request headers:" # Dict not ordered in Python, exact logging order doesn't matter @@ -156,7 +156,7 @@ def emit(self, record): policy = HttpLoggingPolicy() kwargs={'logger': logger} - universal_request = HttpRequest('GET', 'http://127.0.0.1/') + universal_request = HttpRequest('GET', 'http://localhost/') http_response = HttpResponse(universal_request, None) http_response.status_code = 202 request = PipelineRequest(universal_request, PipelineContext(None, **kwargs)) @@ -169,7 +169,7 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 6 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == 'Request headers:' assert mock_handler.messages[3].message == 'No body was attached to the request' @@ -192,13 +192,13 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 12 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == 'Request headers:' assert mock_handler.messages[3].message == 'No body was attached to the request' assert mock_handler.messages[4].message == 'Response status: 202' assert mock_handler.messages[5].message == 'Response headers:' - assert mock_handler.messages[6].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[6].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[7].message == "Request method: 'GET'" assert mock_handler.messages[8].message == 'Request headers:' assert mock_handler.messages[9].message == 'No body was attached to the request' @@ -226,7 +226,7 @@ def emit(self, record): policy = HttpLoggingPolicy(logger=logger) - universal_request = HttpRequest('GET', 'http://127.0.0.1/') + universal_request = HttpRequest('GET', 'http://localhost/') universal_request.body = "testbody" http_response = HttpResponse(universal_request, None) http_response.status_code = 202 @@ -238,7 +238,7 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 6 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == 'Request headers:' assert mock_handler.messages[3].message == 'A body is sent with the request' @@ -267,7 +267,7 @@ def emit(self, record): policy = HttpLoggingPolicy(logger=logger) - universal_request = HttpRequest('GET', 'http://127.0.0.1/') + universal_request = HttpRequest('GET', 'http://localhost/') mock = Mock() mock.__class__ = types.AsyncGeneratorType universal_request.body = mock @@ -281,7 +281,7 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 6 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == 'Request headers:' assert mock_handler.messages[3].message == 'File upload' diff --git a/sdk/core/azure-core/tests/async_tests/test_retry_policy_async.py b/sdk/core/azure-core/tests/async_tests/test_retry_policy_async.py index b77ee80d4bb7..faa0944e6399 100644 --- a/sdk/core/azure-core/tests/async_tests/test_retry_policy_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_retry_policy_async.py @@ -62,7 +62,7 @@ def test_retry_types(): @pytest.mark.parametrize("retry_after_input", [('0'), ('800'), ('1000'), ('1200')]) def test_retry_after(retry_after_input): retry_policy = AsyncRetryPolicy() - request = HttpRequest("GET", "http://127.0.0.1") + request = HttpRequest("GET", "http://localhost") response = HttpResponse(request, None) response.headers["retry-after-ms"] = retry_after_input pipeline_response = PipelineResponse(request, response, None) @@ -80,7 +80,7 @@ def test_retry_after(retry_after_input): @pytest.mark.parametrize("retry_after_input", [('0'), ('800'), ('1000'), ('1200')]) def test_x_ms_retry_after(retry_after_input): retry_policy = AsyncRetryPolicy() - request = HttpRequest("GET", "http://127.0.0.1") + request = HttpRequest("GET", "http://localhost") response = HttpResponse(request, None) response.headers["x-ms-retry-after-ms"] = retry_after_input pipeline_response = PipelineResponse(request, response, None) @@ -113,7 +113,7 @@ async def send(self, request, **kwargs): # type: (PipelineRequest, Any) -> Pipe response.status_code = 429 return response - http_request = HttpRequest('GET', 'http://127.0.0.1/') + http_request = HttpRequest('GET', 'http://localhost/') http_retry = AsyncRetryPolicy(retry_total = 1) transport = MockTransport() pipeline = AsyncPipeline(transport, [http_retry]) @@ -140,7 +140,7 @@ async def send(self, request, **kwargs): # type: (PipelineRequest, Any) -> Pipe response.headers = headers return response - http_request = HttpRequest('GET', 'http://127.0.0.1/') + http_request = HttpRequest('GET', 'http://localhost/') http_retry = AsyncRetryPolicy(retry_total = 1) transport = MockTransport() pipeline = AsyncPipeline(transport, [http_retry]) @@ -171,7 +171,7 @@ async def send(self, request, **kwargs): # type: (PipelineRequest, Any) -> Pipe return response data = BytesIO(b"Lots of dataaaa") - http_request = HttpRequest('GET', 'http://127.0.0.1/') + http_request = HttpRequest('GET', 'http://localhost/') http_request.set_streamed_data_body(data) http_retry = AsyncRetryPolicy(retry_total = 1) pipeline = AsyncPipeline(MockTransport(), [http_retry]) @@ -209,7 +209,7 @@ async def send(self, request, **kwargs): # type: (PipelineRequest, Any) -> Pipe file = tempfile.NamedTemporaryFile(delete=False) file.write(b'Lots of dataaaa') file.close() - http_request = HttpRequest('GET', 'http://127.0.0.1/') + http_request = HttpRequest('GET', 'http://localhost/') headers = {'Content-Type': "multipart/form-data"} http_request.headers = headers with open(file.name, 'rb') as f: @@ -241,7 +241,7 @@ def send(request, **kwargs): pipeline = AsyncPipeline(transport, [AsyncRetryPolicy(timeout=timeout)]) with pytest.raises(ServiceResponseTimeoutError): - await pipeline.run(HttpRequest("GET", "http://127.0.0.1/")) + await pipeline.run(HttpRequest("GET", "http://localhost/")) @pytest.mark.asyncio @@ -262,7 +262,7 @@ async def send(request, **kwargs): ) pipeline = AsyncPipeline(transport, [AsyncRetryPolicy()]) - await pipeline.run(HttpRequest("GET", "http://127.0.0.1/")) + await pipeline.run(HttpRequest("GET", "http://localhost/")) assert transport.send.call_count == 1, "policy should not retry: its first send succeeded" @@ -284,6 +284,6 @@ async def test_does_not_sleep_after_timeout(transport_error, expected_timeout_er pipeline = AsyncPipeline(transport, [AsyncRetryPolicy(timeout=timeout)]) with pytest.raises(expected_timeout_error): - await pipeline.run(HttpRequest("GET", "http://127.0.0.1/")) + await pipeline.run(HttpRequest("GET", "http://localhost/")) assert transport.sleep.call_count == 1 diff --git a/sdk/core/azure-core/tests/async_tests/test_stream_generator_async.py b/sdk/core/azure-core/tests/async_tests/test_stream_generator_async.py index de7bc894e42d..d90b5b15b4c9 100644 --- a/sdk/core/azure-core/tests/async_tests/test_stream_generator_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_stream_generator_async.py @@ -38,7 +38,7 @@ async def open(self): pass async def send(self, request, **kwargs): - request = HttpRequest('GET', 'http://127.0.0.1/') + request = HttpRequest('GET', 'http://localhost/') response = AsyncHttpResponse(request, None) response.status_code = 200 return response @@ -65,7 +65,7 @@ class AsyncMock(mock.MagicMock): async def __call__(self, *args, **kwargs): return super(AsyncMock, self).__call__(*args, **kwargs) - http_request = HttpRequest('GET', 'http://127.0.0.1/') + http_request = HttpRequest('GET', 'http://localhost/') pipeline = AsyncPipeline(MockTransport()) http_response = AsyncHttpResponse(http_request, None) http_response.internal_response = MockInternalResponse() diff --git a/sdk/core/azure-core/tests/async_tests/test_tracing_decorator_async.py b/sdk/core/azure-core/tests/async_tests/test_tracing_decorator_async.py index e1b602268379..62b606218a0e 100644 --- a/sdk/core/azure-core/tests/async_tests/test_tracing_decorator_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_tracing_decorator_async.py @@ -31,7 +31,7 @@ class MockClient: @distributed_trace def __init__(self, policies=None, assert_current_span=False): time.sleep(0.001) - self.request = HttpRequest("GET", "http://127.0.0.1") + self.request = HttpRequest("GET", "http://localhost") if policies is None: policies = [] policies.append(mock.Mock(spec=HTTPPolicy, send=self.verify_request)) diff --git a/sdk/core/azure-core/tests/test_custom_hook_policy.py b/sdk/core/azure-core/tests/test_custom_hook_policy.py index ce4e9638a7cf..e553ca5a9811 100644 --- a/sdk/core/azure-core/tests/test_custom_hook_policy.py +++ b/sdk/core/azure-core/tests/test_custom_hook_policy.py @@ -17,7 +17,7 @@ def test_callback(response): raise ValueError() transport = mock.MagicMock(spec=HttpTransport) - url = "http://127.0.0.1" + url = "http://localhost" custom_hook_policy = CustomHookPolicy(raw_response_hook=test_callback) policies = [ UserAgentPolicy("myuseragent"), @@ -33,7 +33,7 @@ def test_callback(response): raise ValueError() transport = mock.MagicMock(spec=HttpTransport) - url = "http://127.0.0.1" + url = "http://localhost" custom_hook_policy = CustomHookPolicy() policies = [ UserAgentPolicy("myuseragent"), @@ -52,7 +52,7 @@ def test_callback_request(response): raise TypeError() transport = mock.MagicMock(spec=HttpTransport) - url = "http://127.0.0.1" + url = "http://localhost" custom_hook_policy = CustomHookPolicy(raw_response_hook=test_callback) policies = [ UserAgentPolicy("myuseragent"), @@ -68,7 +68,7 @@ def test_callback(response): raise ValueError() transport = mock.MagicMock(spec=HttpTransport) - url = "http://127.0.0.1" + url = "http://localhost" custom_hook_policy = CustomHookPolicy(raw_request_hook=test_callback) policies = [ UserAgentPolicy("myuseragent"), @@ -84,7 +84,7 @@ def test_callback(response): raise ValueError() transport = mock.MagicMock(spec=HttpTransport) - url = "http://127.0.0.1" + url = "http://localhost" custom_hook_policy = CustomHookPolicy() policies = [ UserAgentPolicy("myuseragent"), @@ -103,7 +103,7 @@ def test_callback_request(response): raise TypeError() transport = mock.MagicMock(spec=HttpTransport) - url = "http://127.0.0.1" + url = "http://localhost" custom_hook_policy = CustomHookPolicy(raw_request_hook=test_callback) policies = [ UserAgentPolicy("myuseragent"), diff --git a/sdk/core/azure-core/tests/test_http_logging_policy.py b/sdk/core/azure-core/tests/test_http_logging_policy.py index bd427bdc3e79..c69b8b5f0e7c 100644 --- a/sdk/core/azure-core/tests/test_http_logging_policy.py +++ b/sdk/core/azure-core/tests/test_http_logging_policy.py @@ -42,7 +42,7 @@ def emit(self, record): policy = HttpLoggingPolicy(logger=logger) - universal_request = HttpRequest('GET', 'http://127.0.0.1/') + universal_request = HttpRequest('GET', 'http://localhost/') http_response = HttpResponse(universal_request, None) http_response.status_code = 202 request = PipelineRequest(universal_request, PipelineContext(None)) @@ -55,7 +55,7 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 6 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == 'Request headers:' assert mock_handler.messages[3].message == 'No body was attached to the request' @@ -76,13 +76,13 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 12 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == 'Request headers:' assert mock_handler.messages[3].message == 'No body was attached to the request' assert mock_handler.messages[4].message == 'Response status: 202' assert mock_handler.messages[5].message == 'Response headers:' - assert mock_handler.messages[6].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[6].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[7].message == "Request method: 'GET'" assert mock_handler.messages[8].message == 'Request headers:' assert mock_handler.messages[9].message == 'No body was attached to the request' @@ -103,7 +103,7 @@ def emit(self, record): "Content-Type": "Caramel", "HateToo": "Chocolat", } - universal_request.url = "http://127.0.0.1/?country=france&city=aix" + universal_request.url = "http://localhost/?country=france&city=aix" policy.on_request(request) response = PipelineResponse(request, http_response, request.context) @@ -111,7 +111,7 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 10 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/?country=france&city=REDACTED'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/?country=france&city=REDACTED'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == "Request headers:" # Dict not ordered in Python, exact logging order doesn't matter @@ -157,7 +157,7 @@ def emit(self, record): policy = HttpLoggingPolicy() kwargs={'logger': logger} - universal_request = HttpRequest('GET', 'http://127.0.0.1/') + universal_request = HttpRequest('GET', 'http://localhost/') http_response = HttpResponse(universal_request, None) http_response.status_code = 202 request = PipelineRequest(universal_request, PipelineContext(None, **kwargs)) @@ -170,7 +170,7 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 6 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == 'Request headers:' assert mock_handler.messages[3].message == 'No body was attached to the request' @@ -193,13 +193,13 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 12 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == 'Request headers:' assert mock_handler.messages[3].message == 'No body was attached to the request' assert mock_handler.messages[4].message == 'Response status: 202' assert mock_handler.messages[5].message == 'Response headers:' - assert mock_handler.messages[6].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[6].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[7].message == "Request method: 'GET'" assert mock_handler.messages[8].message == 'Request headers:' assert mock_handler.messages[9].message == 'No body was attached to the request' @@ -227,7 +227,7 @@ def emit(self, record): policy = HttpLoggingPolicy(logger=logger) - universal_request = HttpRequest('GET', 'http://127.0.0.1/') + universal_request = HttpRequest('GET', 'http://localhost/') universal_request.body = "testbody" http_response = HttpResponse(universal_request, None) http_response.status_code = 202 @@ -239,7 +239,7 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 6 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == 'Request headers:' assert mock_handler.messages[3].message == 'A body is sent with the request' @@ -267,7 +267,7 @@ def emit(self, record): policy = HttpLoggingPolicy(logger=logger) - universal_request = HttpRequest('GET', 'http://127.0.0.1/') + universal_request = HttpRequest('GET', 'http://localhost/') mock = Mock() mock.__class__ = types.GeneratorType universal_request.body = mock @@ -281,7 +281,7 @@ def emit(self, record): assert all(m.levelname == 'INFO' for m in mock_handler.messages) assert len(mock_handler.messages) == 6 - assert mock_handler.messages[0].message == "Request URL: 'http://127.0.0.1/'" + assert mock_handler.messages[0].message == "Request URL: 'http://localhost/'" assert mock_handler.messages[1].message == "Request method: 'GET'" assert mock_handler.messages[2].message == 'Request headers:' assert mock_handler.messages[3].message == 'File upload' diff --git a/sdk/core/azure-core/tests/test_request_id_policy.py b/sdk/core/azure-core/tests/test_request_id_policy.py index a118128ece1c..7da467b467c2 100644 --- a/sdk/core/azure-core/tests/test_request_id_policy.py +++ b/sdk/core/azure-core/tests/test_request_id_policy.py @@ -30,7 +30,7 @@ def test_request_id_policy(auto_request_id, request_id_init, request_id_set, req request_id_policy = RequestIdPolicy(**kwargs) if request_id_set != "_unset": request_id_policy.set_request_id(request_id_set) - request = HttpRequest('GET', 'http://127.0.0.1/') + request = HttpRequest('GET', 'http://localhost/') pipeline_request = PipelineRequest(request, PipelineContext(None)) if request_id_req != "_unset": pipeline_request.context.options['request_id'] = request_id_req @@ -58,7 +58,7 @@ def test_request_id_policy(auto_request_id, request_id_init, request_id_set, req def test_request_id_already_exists(): """Test policy with no other policy and happy path""" request_id_policy = RequestIdPolicy() - request = HttpRequest('GET', 'http://127.0.0.1/') + request = HttpRequest('GET', 'http://localhost/') request.headers["x-ms-client-request-id"] = "VALUE" pipeline_request = PipelineRequest(request, PipelineContext(None)) request_id_policy.on_request(pipeline_request) diff --git a/sdk/core/azure-core/tests/test_retry_policy.py b/sdk/core/azure-core/tests/test_retry_policy.py index 10c3acb2520a..ce1a590fba26 100644 --- a/sdk/core/azure-core/tests/test_retry_policy.py +++ b/sdk/core/azure-core/tests/test_retry_policy.py @@ -65,7 +65,7 @@ def test_retry_types(): @pytest.mark.parametrize("retry_after_input", [('0'), ('800'), ('1000'), ('1200')]) def test_retry_after(retry_after_input): retry_policy = RetryPolicy() - request = HttpRequest("GET", "http://127.0.0.1") + request = HttpRequest("GET", "http://localhost") response = HttpResponse(request, None) response.headers["retry-after-ms"] = retry_after_input pipeline_response = PipelineResponse(request, response, None) @@ -83,7 +83,7 @@ def test_retry_after(retry_after_input): @pytest.mark.parametrize("retry_after_input", [('0'), ('800'), ('1000'), ('1200')]) def test_x_ms_retry_after(retry_after_input): retry_policy = RetryPolicy() - request = HttpRequest("GET", "http://127.0.0.1") + request = HttpRequest("GET", "http://localhost") response = HttpResponse(request, None) response.headers["x-ms-retry-after-ms"] = retry_after_input pipeline_response = PipelineResponse(request, response, None) @@ -115,7 +115,7 @@ def send(self, request, **kwargs): # type: (PipelineRequest, Any) -> PipelineRe response.status_code = 429 return response - http_request = HttpRequest('GET', 'http://127.0.0.1/') + http_request = HttpRequest('GET', 'http://localhost/') http_retry = RetryPolicy(retry_total = 1) transport = MockTransport() pipeline = Pipeline(transport, [http_retry]) @@ -141,7 +141,7 @@ def send(self, request, **kwargs): # type: (PipelineRequest, Any) -> PipelineRe response.headers = headers return response - http_request = HttpRequest('GET', 'http://127.0.0.1/') + http_request = HttpRequest('GET', 'http://localhost/') http_retry = RetryPolicy(retry_total = 1) transport = MockTransport() pipeline = Pipeline(transport, [http_retry]) @@ -171,7 +171,7 @@ def send(self, request, **kwargs): # type: (PipelineRequest, Any) -> PipelineRe return response data = BytesIO(b"Lots of dataaaa") - http_request = HttpRequest('GET', 'http://127.0.0.1/') + http_request = HttpRequest('GET', 'http://localhost/') http_request.set_streamed_data_body(data) http_retry = RetryPolicy(retry_total = 1) pipeline = Pipeline(MockTransport(), [http_retry]) @@ -208,7 +208,7 @@ def send(self, request, **kwargs): # type: (PipelineRequest, Any) -> PipelineRe file = tempfile.NamedTemporaryFile(delete=False) file.write(b'Lots of dataaaa') file.close() - http_request = HttpRequest('GET', 'http://127.0.0.1/') + http_request = HttpRequest('GET', 'http://localhost/') headers = {'Content-Type': "multipart/form-data"} http_request.headers = headers with open(file.name, 'rb') as f: @@ -239,7 +239,7 @@ def send(request, **kwargs): pipeline = Pipeline(transport, [RetryPolicy(timeout=timeout)]) with pytest.raises(ServiceResponseTimeoutError): - response = pipeline.run(HttpRequest("GET", "http://127.0.0.1/")) + response = pipeline.run(HttpRequest("GET", "http://localhost/")) def test_timeout_defaults(): @@ -259,7 +259,7 @@ def send(request, **kwargs): ) pipeline = Pipeline(transport, [RetryPolicy()]) - pipeline.run(HttpRequest("GET", "http://127.0.0.1/")) + pipeline.run(HttpRequest("GET", "http://localhost/")) assert transport.send.call_count == 1, "policy should not retry: its first send succeeded" @@ -280,6 +280,6 @@ def test_does_not_sleep_after_timeout(transport_error, expected_timeout_error): pipeline = Pipeline(transport, [RetryPolicy(timeout=timeout)]) with pytest.raises(expected_timeout_error): - pipeline.run(HttpRequest("GET", "http://127.0.0.1/")) + pipeline.run(HttpRequest("GET", "http://localhost/")) assert transport.sleep.call_count == 1 diff --git a/sdk/core/azure-core/tests/test_stream_generator.py b/sdk/core/azure-core/tests/test_stream_generator.py index c43053eeab9d..1d8b3c7172c4 100644 --- a/sdk/core/azure-core/tests/test_stream_generator.py +++ b/sdk/core/azure-core/tests/test_stream_generator.py @@ -31,7 +31,7 @@ def open(self): pass def send(self, request, **kwargs): - request = HttpRequest('GET', 'http://127.0.0.1/') + request = HttpRequest('GET', 'http://localhost/') response = HttpResponse(request, None) response.status_code = 200 return response @@ -58,7 +58,7 @@ def __init__(self): def close(self): pass - http_request = HttpRequest('GET', 'http://127.0.0.1/') + http_request = HttpRequest('GET', 'http://localhost/') pipeline = Pipeline(MockTransport()) http_response = HttpResponse(http_request, None) http_response.internal_response = MockInternalResponse() diff --git a/sdk/core/azure-core/tests/test_tracing_decorator.py b/sdk/core/azure-core/tests/test_tracing_decorator.py index 140e3b0656ac..be9a820747e3 100644 --- a/sdk/core/azure-core/tests/test_tracing_decorator.py +++ b/sdk/core/azure-core/tests/test_tracing_decorator.py @@ -30,7 +30,7 @@ class MockClient: @distributed_trace def __init__(self, policies=None, assert_current_span=False): time.sleep(0.001) - self.request = HttpRequest("GET", "http://127.0.0.1") + self.request = HttpRequest("GET", "http://localhost") if policies is None: policies = [] policies.append(mock.Mock(spec=HTTPPolicy, send=self.verify_request)) diff --git a/sdk/core/azure-core/tests/test_tracing_policy.py b/sdk/core/azure-core/tests/test_tracing_policy.py index 743d2078acb5..2a0fc03a78e7 100644 --- a/sdk/core/azure-core/tests/test_tracing_policy.py +++ b/sdk/core/azure-core/tests/test_tracing_policy.py @@ -24,7 +24,7 @@ def test_distributed_tracing_policy_solo(): with FakeSpan(name="parent") as root_span: policy = DistributedTracingPolicy() - request = HttpRequest("GET", "http://127.0.0.1/temp?query=query") + request = HttpRequest("GET", "http://localhost/temp?query=query") request.headers["x-ms-client-request-id"] = "some client request id" pipeline_request = PipelineRequest(request, PipelineContext(None)) @@ -50,7 +50,7 @@ def test_distributed_tracing_policy_solo(): assert network_span.name == "/temp" assert network_span.attributes.get("http.method") == "GET" assert network_span.attributes.get("component") == "http" - assert network_span.attributes.get("http.url") == "http://127.0.0.1/temp?query=query" + assert network_span.attributes.get("http.url") == "http://localhost/temp?query=query" assert network_span.attributes.get("http.user_agent") is None assert network_span.attributes.get("x-ms-request-id") == "some request id" assert network_span.attributes.get("x-ms-client-request-id") == "some client request id" @@ -61,7 +61,7 @@ def test_distributed_tracing_policy_solo(): assert network_span.name == "/temp" assert network_span.attributes.get("http.method") == "GET" assert network_span.attributes.get("component") == "http" - assert network_span.attributes.get("http.url") == "http://127.0.0.1/temp?query=query" + assert network_span.attributes.get("http.url") == "http://localhost/temp?query=query" assert network_span.attributes.get("x-ms-client-request-id") == "some client request id" assert network_span.attributes.get("http.user_agent") is None assert network_span.attributes.get("x-ms-request-id") == None @@ -76,7 +76,7 @@ def test_distributed_tracing_policy_attributes(): 'myattr': 'myvalue' }) - request = HttpRequest("GET", "http://127.0.0.1/temp?query=query") + request = HttpRequest("GET", "http://localhost/temp?query=query") pipeline_request = PipelineRequest(request, PipelineContext(None)) policy.on_request(pipeline_request) @@ -132,7 +132,7 @@ def test_distributed_tracing_policy_with_user_agent(): with FakeSpan(name="parent") as root_span: policy = DistributedTracingPolicy() - request = HttpRequest("GET", "http://127.0.0.1") + request = HttpRequest("GET", "http://localhost") request.headers["x-ms-client-request-id"] = "some client request id" pipeline_request = PipelineRequest(request, PipelineContext(None)) @@ -164,7 +164,7 @@ def test_distributed_tracing_policy_with_user_agent(): assert network_span.name == "/" assert network_span.attributes.get("http.method") == "GET" assert network_span.attributes.get("component") == "http" - assert network_span.attributes.get("http.url") == "http://127.0.0.1" + assert network_span.attributes.get("http.url") == "http://localhost" assert network_span.attributes.get("http.user_agent").endswith("mytools") assert network_span.attributes.get("x-ms-request-id") == "some request id" assert network_span.attributes.get("x-ms-client-request-id") == "some client request id" @@ -174,7 +174,7 @@ def test_distributed_tracing_policy_with_user_agent(): assert network_span.name == "/" assert network_span.attributes.get("http.method") == "GET" assert network_span.attributes.get("component") == "http" - assert network_span.attributes.get("http.url") == "http://127.0.0.1" + assert network_span.attributes.get("http.url") == "http://localhost" assert network_span.attributes.get("http.user_agent").endswith("mytools") assert network_span.attributes.get("x-ms-client-request-id") == "some client request id" assert network_span.attributes.get("x-ms-request-id") is None @@ -187,7 +187,7 @@ def test_span_namer(): settings.tracing_implementation.set_value(FakeSpan) with FakeSpan(name="parent") as root_span: - request = HttpRequest("GET", "http://127.0.0.1/temp?query=query") + request = HttpRequest("GET", "http://localhost/temp?query=query") pipeline_request = PipelineRequest(request, PipelineContext(None)) def fixed_namer(http_request): diff --git a/sdk/core/azure-core/tests/test_universal_pipeline.py b/sdk/core/azure-core/tests/test_universal_pipeline.py index b14f63fd7931..ea5676374458 100644 --- a/sdk/core/azure-core/tests/test_universal_pipeline.py +++ b/sdk/core/azure-core/tests/test_universal_pipeline.py @@ -92,7 +92,7 @@ def __deepcopy__(self, memodict={}): raise ValueError() body = Non_deep_copiable() - request = HttpRequest('GET', 'http://127.0.0.1/', {'user-agent': 'test_request_history'}) + request = HttpRequest('GET', 'http://localhost/', {'user-agent': 'test_request_history'}) request.body = body request_history = RequestHistory(request) assert request_history.http_request.headers == request.headers @@ -105,7 +105,7 @@ def __deepcopy__(self, memodict={}): raise TypeError() body = Non_deep_copiable() - request = HttpRequest('GET', 'http://127.0.0.1/', {'user-agent': 'test_request_history'}) + request = HttpRequest('GET', 'http://localhost/', {'user-agent': 'test_request_history'}) request.body = body request_history = RequestHistory(request) assert request_history.http_request.headers == request.headers @@ -114,7 +114,7 @@ def __deepcopy__(self, memodict={}): @mock.patch('azure.core.pipeline.policies._universal._LOGGER') def test_no_log(mock_http_logger): - universal_request = HttpRequest('GET', 'http://127.0.0.1/') + universal_request = HttpRequest('GET', 'http://localhost/') request = PipelineRequest(universal_request, PipelineContext(None)) http_logger = NetworkTraceLoggingPolicy() response = PipelineResponse(request, HttpResponse(universal_request, None), request.context) @@ -191,7 +191,7 @@ def send(*args): def test_raw_deserializer(): raw_deserializer = ContentDecodePolicy() context = PipelineContext(None, stream=False) - universal_request = HttpRequest('GET', 'http://127.0.0.1/') + universal_request = HttpRequest('GET', 'http://localhost/') request = PipelineRequest(universal_request, context) def build_response(body, content_type=None): diff --git a/sdk/core/azure-core/tests/test_user_agent_policy.py b/sdk/core/azure-core/tests/test_user_agent_policy.py index 239daffbe63d..4f8b01c93b7e 100644 --- a/sdk/core/azure-core/tests/test_user_agent_policy.py +++ b/sdk/core/azure-core/tests/test_user_agent_policy.py @@ -21,7 +21,7 @@ def test_user_agent_policy(): user_agent = UserAgentPolicy(base_user_agent='foo', user_agent='bar', user_agent_use_env=False) assert user_agent._user_agent == 'bar foo' - request = HttpRequest('GET', 'http://127.0.0.1/') + request = HttpRequest('GET', 'http://localhost/') pipeline_request = PipelineRequest(request, PipelineContext(None)) pipeline_request.context.options['user_agent'] = 'xyz' @@ -35,6 +35,6 @@ def test_user_agent_environ(): policy = UserAgentPolicy(None) assert policy.user_agent.endswith("mytools") - request = HttpRequest('GET', 'http://127.0.0.1/') + request = HttpRequest('GET', 'http://localhost/') policy.on_request(PipelineRequest(request, PipelineContext(None))) assert request.headers["user-agent"].endswith("mytools") diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_request.py b/sdk/core/azure-core/tests/testserver_tests/test_rest_http_request.py index a41a911c3a6d..e0ae70642431 100644 --- a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_request.py +++ b/sdk/core/azure-core/tests/testserver_tests/test_rest_http_request.py @@ -204,7 +204,7 @@ def test_multipart_invalid_key(key): files = {"file": io.BytesIO(b"")} with pytest.raises(TypeError) as e: HttpRequest( - url="http://127.0.0.1:8000/", + url="http://localhost:8000/", method="POST", data=data, files=files, @@ -221,7 +221,7 @@ def test_multipart_invalid_key_binary_string(): files = {"file": io.BytesIO(b"")} with pytest.raises(TypeError) as e: HttpRequest( - url="http://127.0.0.1:8000/", + url="http://localhost:8000/", method="POST", data=data, files=files, @@ -235,7 +235,7 @@ def test_multipart_invalid_value(value): data = {"text": value} files = {"file": io.BytesIO(b"")} with pytest.raises(TypeError) as e: - HttpRequest("POST", "http://127.0.0.1:8000/", data=data, files=files) + HttpRequest("POST", "http://localhost:8000/", data=data, files=files) assert "Invalid type for data value" in str(e.value) def test_empty_request(): From e5f7a5229e3ddc997ca4752ff9a74010655901b0 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Thu, 19 Aug 2021 13:01:37 -0700 Subject: [PATCH 4/6] update --- .../async_tests/conftest.py | 0 .../async_tests/rest_client_async.py | 2 +- .../async_tests/test_basic_transport_async.py | 18 ++- .../tests/async_tests/test_pipeline_async.py | 74 +++++++++ .../tests/async_tests/test_request_asyncio.py | 13 +- .../tests/async_tests/test_request_trio.py | 8 +- .../test_rest_asyncio_transport.py | 8 +- .../test_rest_context_manager_async.py | 2 +- .../async_tests/test_rest_headers_async.py | 2 +- .../test_rest_http_request_async.py | 3 +- .../test_rest_http_response_async.py | 0 .../test_rest_stream_responses_async.py | 3 - .../async_tests/test_rest_trio_transport.py | 6 +- .../async_tests/test_testserver_async.py | 2 +- .../async_tests/test_universal_http_async.py | 57 ++++++- sdk/core/azure-core/tests/conftest.py | 62 +++++++ .../{testserver_tests => }/rest_client.py | 2 +- .../azure-core/tests/test_basic_transport.py | 59 ++++++- sdk/core/azure-core/tests/test_exceptions.py | 14 ++ sdk/core/azure-core/tests/test_pipeline.py | 64 ++++++++ .../tests/test_requests_universal.py | 9 +- .../test_rest_context_manager.py | 0 .../test_rest_headers.py | 0 .../test_rest_http_request.py | 1 - .../test_rest_http_response.py | 0 .../{testserver_tests => }/test_rest_query.py | 2 +- .../test_rest_stream_responses.py | 0 .../{testserver_tests => }/test_testserver.py | 1 - .../test_basic_transport_async_test_server.py | 22 --- .../test_pipeline_async_test_server.py | 118 -------------- .../test_universal_http_async_test_server.py | 89 ---------- .../tests/testserver_tests/conftest.py | 92 ----------- .../coretestserver/test_routes/basic.py | 19 ++- .../coretestserver/test_routes/helpers.py | 153 +++++++++++++++++- .../coretestserver/test_routes/structures.py | 19 +++ .../test_basic_transport_test_server.py | 66 -------- .../test_exceptions_test_server.py | 40 ----- .../test_pipeline_test_server.py | 105 ------------ .../test_requests_universal_test_server.py | 33 ---- 39 files changed, 554 insertions(+), 614 deletions(-) rename sdk/core/azure-core/tests/{testserver_tests => }/async_tests/conftest.py (100%) rename sdk/core/azure-core/tests/{testserver_tests => }/async_tests/rest_client_async.py (98%) rename sdk/core/azure-core/tests/{testserver_tests => }/async_tests/test_rest_asyncio_transport.py (83%) rename sdk/core/azure-core/tests/{testserver_tests => }/async_tests/test_rest_context_manager_async.py (97%) rename sdk/core/azure-core/tests/{testserver_tests => }/async_tests/test_rest_headers_async.py (98%) rename sdk/core/azure-core/tests/{testserver_tests => }/async_tests/test_rest_http_request_async.py (98%) rename sdk/core/azure-core/tests/{testserver_tests => }/async_tests/test_rest_http_response_async.py (100%) rename sdk/core/azure-core/tests/{testserver_tests => }/async_tests/test_rest_stream_responses_async.py (99%) rename sdk/core/azure-core/tests/{testserver_tests => }/async_tests/test_rest_trio_transport.py (82%) rename sdk/core/azure-core/tests/{testserver_tests => }/async_tests/test_testserver_async.py (97%) rename sdk/core/azure-core/tests/{testserver_tests => }/rest_client.py (99%) rename sdk/core/azure-core/tests/{testserver_tests => }/test_rest_context_manager.py (100%) rename sdk/core/azure-core/tests/{testserver_tests => }/test_rest_headers.py (100%) rename sdk/core/azure-core/tests/{testserver_tests => }/test_rest_http_request.py (99%) rename sdk/core/azure-core/tests/{testserver_tests => }/test_rest_http_response.py (100%) rename sdk/core/azure-core/tests/{testserver_tests => }/test_rest_query.py (99%) rename sdk/core/azure-core/tests/{testserver_tests => }/test_rest_stream_responses.py (100%) rename sdk/core/azure-core/tests/{testserver_tests => }/test_testserver.py (99%) delete mode 100644 sdk/core/azure-core/tests/testserver_tests/async_tests/test_basic_transport_async_test_server.py delete mode 100644 sdk/core/azure-core/tests/testserver_tests/async_tests/test_pipeline_async_test_server.py delete mode 100644 sdk/core/azure-core/tests/testserver_tests/async_tests/test_universal_http_async_test_server.py delete mode 100644 sdk/core/azure-core/tests/testserver_tests/conftest.py create mode 100644 sdk/core/azure-core/tests/testserver_tests/coretestserver/coretestserver/test_routes/structures.py delete mode 100644 sdk/core/azure-core/tests/testserver_tests/test_basic_transport_test_server.py delete mode 100644 sdk/core/azure-core/tests/testserver_tests/test_exceptions_test_server.py delete mode 100644 sdk/core/azure-core/tests/testserver_tests/test_pipeline_test_server.py delete mode 100644 sdk/core/azure-core/tests/testserver_tests/test_requests_universal_test_server.py diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/conftest.py b/sdk/core/azure-core/tests/async_tests/conftest.py similarity index 100% rename from sdk/core/azure-core/tests/testserver_tests/async_tests/conftest.py rename to sdk/core/azure-core/tests/async_tests/conftest.py diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/rest_client_async.py b/sdk/core/azure-core/tests/async_tests/rest_client_async.py similarity index 98% rename from sdk/core/azure-core/tests/testserver_tests/async_tests/rest_client_async.py rename to sdk/core/azure-core/tests/async_tests/rest_client_async.py index 1f2e3568bb02..2ad83c2dea4c 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/rest_client_async.py +++ b/sdk/core/azure-core/tests/async_tests/rest_client_async.py @@ -66,4 +66,4 @@ async def __aenter__(self): return self async def __aexit__(self, *exc_details) -> None: - await self._client.__aexit__(*exc_details) \ No newline at end of file + await self._client.__aexit__(*exc_details) diff --git a/sdk/core/azure-core/tests/async_tests/test_basic_transport_async.py b/sdk/core/azure-core/tests/async_tests/test_basic_transport_async.py index 4f89cc552fd7..75a8ce4d8e9f 100644 --- a/sdk/core/azure-core/tests/async_tests/test_basic_transport_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_basic_transport_async.py @@ -3,14 +3,6 @@ # Licensed under the MIT License. See LICENSE.txt in the project root for # license information. # ------------------------------------------------------------------------- -from six.moves.http_client import HTTPConnection -import time - -try: - from unittest import mock -except ImportError: - import mock - from azure.core.pipeline.transport import HttpRequest, AsyncHttpResponse, AsyncHttpTransport, AioHttpTransport from azure.core.pipeline.policies import HeadersPolicy from azure.core.pipeline import AsyncPipeline @@ -933,3 +925,13 @@ async def test_recursive_multipart_receive(): internal_response0 = internal_parts[0] assert internal_response0.status_code == 400 + +@pytest.mark.asyncio +async def test_basic_options_aiohttp(port): + + request = HttpRequest("OPTIONS", "http://localhost:{}/basic/string".format(port)) + async with AsyncPipeline(AioHttpTransport(), policies=[]) as pipeline: + response = await pipeline.run(request) + + assert pipeline._transport.session is None + assert isinstance(response.http_response.status_code, int) diff --git a/sdk/core/azure-core/tests/async_tests/test_pipeline_async.py b/sdk/core/azure-core/tests/async_tests/test_pipeline_async.py index 96d71cfa3973..17a5ad0248ea 100644 --- a/sdk/core/azure-core/tests/async_tests/test_pipeline_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_pipeline_async.py @@ -247,3 +247,77 @@ def send(*args): client = AsyncPipelineClient(base_url="test", policies=policies, per_retry_policies=foo_policy) with pytest.raises(ValueError): client = AsyncPipelineClient(base_url="test", policies=policies, per_retry_policies=[foo_policy]) + +@pytest.mark.asyncio +async def test_basic_aiohttp(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + async with AsyncPipeline(AioHttpTransport(), policies=policies) as pipeline: + response = await pipeline.run(request) + + assert pipeline._transport.session is None + # all we need to check is if we are able to make the call + assert isinstance(response.http_response.status_code, int) + +@pytest.mark.asyncio +async def test_basic_aiohttp_separate_session(port): + + session = aiohttp.ClientSession() + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + transport = AioHttpTransport(session=session, session_owner=False) + async with AsyncPipeline(transport, policies=policies) as pipeline: + response = await pipeline.run(request) + + assert transport.session + assert isinstance(response.http_response.status_code, int) + await transport.close() + assert transport.session + await transport.session.close() + +@pytest.mark.asyncio +async def test_basic_async_requests(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + async with AsyncPipeline(AsyncioRequestsTransport(), policies=policies) as pipeline: + response = await pipeline.run(request) + + assert isinstance(response.http_response.status_code, int) + +@pytest.mark.asyncio +async def test_conf_async_requests(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + async with AsyncPipeline(AsyncioRequestsTransport(), policies=policies) as pipeline: + response = await pipeline.run(request) + + assert isinstance(response.http_response.status_code, int) + +def test_conf_async_trio_requests(port): + + async def do(): + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + async with AsyncPipeline(TrioRequestsTransport(), policies=policies) as pipeline: + return await pipeline.run(request) + + response = trio.run(do) + assert isinstance(response.http_response.status_code, int) diff --git a/sdk/core/azure-core/tests/async_tests/test_request_asyncio.py b/sdk/core/azure-core/tests/async_tests/test_request_asyncio.py index 92097a2265d8..d07b23f29540 100644 --- a/sdk/core/azure-core/tests/async_tests/test_request_asyncio.py +++ b/sdk/core/azure-core/tests/async_tests/test_request_asyncio.py @@ -11,7 +11,7 @@ @pytest.mark.asyncio -async def test_async_gen_data(): +async def test_async_gen_data(port): class AsyncGen: def __init__(self): self._range = iter([b"azerty"]) @@ -26,14 +26,15 @@ async def __anext__(self): raise StopAsyncIteration async with AsyncioRequestsTransport() as transport: - req = HttpRequest('GET', 'http://httpbin.org/anything', data=AsyncGen()) + req = HttpRequest('GET', 'http://localhost:{}/basic/anything'.format(port), data=AsyncGen()) response = await transport.send(req) + text = response.text() assert json.loads(response.text())['data'] == "azerty" @pytest.mark.asyncio -async def test_send_data(): +async def test_send_data(port): async with AsyncioRequestsTransport() as transport: - req = HttpRequest('PUT', 'http://httpbin.org/anything', data=b"azerty") + req = HttpRequest('PUT', 'http://localhost:{}/basic/anything'.format(port), data=b"azerty") response = await transport.send(req) - - assert json.loads(response.text())['data'] == "azerty" \ No newline at end of file + text = response.text() + assert json.loads(response.text())['data'] == "azerty" diff --git a/sdk/core/azure-core/tests/async_tests/test_request_trio.py b/sdk/core/azure-core/tests/async_tests/test_request_trio.py index 2ab07bd5aa61..11a0058404f5 100644 --- a/sdk/core/azure-core/tests/async_tests/test_request_trio.py +++ b/sdk/core/azure-core/tests/async_tests/test_request_trio.py @@ -11,7 +11,7 @@ @pytest.mark.trio -async def test_async_gen_data(): +async def test_async_gen_data(port): class AsyncGen: def __init__(self): self._range = iter([b"azerty"]) @@ -26,14 +26,14 @@ async def __anext__(self): raise StopAsyncIteration async with TrioRequestsTransport() as transport: - req = HttpRequest('GET', 'http://httpbin.org/anything', data=AsyncGen()) + req = HttpRequest('GET', 'http://localhost:{}/basic/anything'.format(port), data=AsyncGen()) response = await transport.send(req) assert json.loads(response.text())['data'] == "azerty" @pytest.mark.trio -async def test_send_data(): +async def test_send_data(port): async with TrioRequestsTransport() as transport: - req = HttpRequest('PUT', 'http://httpbin.org/anything', data=b"azerty") + req = HttpRequest('PUT', 'http://localhost:{}/basic/anything'.format(port), data=b"azerty") response = await transport.send(req) assert json.loads(response.text())['data'] == "azerty" \ No newline at end of file diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_asyncio_transport.py b/sdk/core/azure-core/tests/async_tests/test_rest_asyncio_transport.py similarity index 83% rename from sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_asyncio_transport.py rename to sdk/core/azure-core/tests/async_tests/test_rest_asyncio_transport.py index 126487f92aa7..9f5052cdb4bd 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_asyncio_transport.py +++ b/sdk/core/azure-core/tests/async_tests/test_rest_asyncio_transport.py @@ -3,8 +3,6 @@ # Licensed under the MIT License. See LICENSE.txt in the project root for # license information. # ------------------------------------------------------------------------- -import json - from azure.core.pipeline.transport import AsyncioRequestsTransport from azure.core.rest import HttpRequest from rest_client_async import AsyncTestRestClient @@ -29,7 +27,7 @@ async def __anext__(self): async with AsyncioRequestsTransport() as transport: client = AsyncTestRestClient(port, transport=transport) - request = HttpRequest('GET', 'http://httpbin.org/anything', content=AsyncGen()) + request = HttpRequest('GET', 'http://localhost:{}/basic/anything'.format(port), content=AsyncGen()) response = await client.send_request(request) assert response.json()['data'] == "azerty" @@ -37,7 +35,7 @@ async def __anext__(self): async def test_send_data(port): async with AsyncioRequestsTransport() as transport: client = AsyncTestRestClient(port, transport=transport) - request = HttpRequest('PUT', 'http://httpbin.org/anything', content=b"azerty") + request = HttpRequest('PUT', 'http://localhost:{}/basic/anything'.format(port), content=b"azerty") response = await client.send_request(request) - assert response.json()['data'] == "azerty" \ No newline at end of file + assert response.json()['data'] == "azerty" diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_context_manager_async.py b/sdk/core/azure-core/tests/async_tests/test_rest_context_manager_async.py similarity index 97% rename from sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_context_manager_async.py rename to sdk/core/azure-core/tests/async_tests/test_rest_context_manager_async.py index 4afcac42172f..77f2d0e34b2b 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_context_manager_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_rest_context_manager_async.py @@ -4,7 +4,7 @@ # Licensed under the MIT License. See LICENSE.txt in the project root for # license information. # ------------------------------------------------------------------------- -from azure.core.exceptions import HttpResponseError, ResponseNotReadError +from azure.core.exceptions import ResponseNotReadError import pytest from azure.core.rest import HttpRequest from rest_client_async import AsyncTestRestClient diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_headers_async.py b/sdk/core/azure-core/tests/async_tests/test_rest_headers_async.py similarity index 98% rename from sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_headers_async.py rename to sdk/core/azure-core/tests/async_tests/test_rest_headers_async.py index 4452e326126d..c7c3373fb583 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_headers_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_rest_headers_async.py @@ -33,4 +33,4 @@ async def test_response_headers_case_insensitive(client): response.headers["cAMeLCaSE-hEadER"] == "camelCase" ) - return response \ No newline at end of file + return response diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_request_async.py b/sdk/core/azure-core/tests/async_tests/test_rest_http_request_async.py similarity index 98% rename from sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_request_async.py rename to sdk/core/azure-core/tests/async_tests/test_rest_http_request_async.py index 67f9d419fb31..0d58b9cb36df 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_request_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_rest_http_request_async.py @@ -8,7 +8,6 @@ # Thank you httpx for your wonderful tests! import pytest from azure.core.rest import HttpRequest -from typing import AsyncGenerator import collections.abc @pytest.fixture @@ -87,4 +86,4 @@ async def content(): request = HttpRequest("POST", "http://example.org", content=content()) await assert_aiterator_body(request, b"test 123") # in this case, request._data is what we end up passing to the requests transport - assert isinstance(request._data, collections.abc.AsyncIterable) \ No newline at end of file + assert isinstance(request._data, collections.abc.AsyncIterable) diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py b/sdk/core/azure-core/tests/async_tests/test_rest_http_response_async.py similarity index 100% rename from sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py rename to sdk/core/azure-core/tests/async_tests/test_rest_http_response_async.py diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_stream_responses_async.py b/sdk/core/azure-core/tests/async_tests/test_rest_stream_responses_async.py similarity index 99% rename from sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_stream_responses_async.py rename to sdk/core/azure-core/tests/async_tests/test_rest_stream_responses_async.py index 673148749719..65e29bfabf22 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_stream_responses_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_rest_stream_responses_async.py @@ -4,9 +4,6 @@ # license information. # ------------------------------------------------------------------------- from azure.core.exceptions import HttpResponseError, ServiceRequestError -import functools -import os -import json import pytest from azure.core.rest import HttpRequest from azure.core.exceptions import StreamClosedError, StreamConsumedError, ResponseNotReadError diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_trio_transport.py b/sdk/core/azure-core/tests/async_tests/test_rest_trio_transport.py similarity index 82% rename from sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_trio_transport.py rename to sdk/core/azure-core/tests/async_tests/test_rest_trio_transport.py index 7e563ca3d6c5..ba9981df6697 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_trio_transport.py +++ b/sdk/core/azure-core/tests/async_tests/test_rest_trio_transport.py @@ -27,15 +27,15 @@ async def __anext__(self): async with TrioRequestsTransport() as transport: client = AsyncTestRestClient(port, transport=transport) - request = HttpRequest('GET', 'http://httpbin.org/anything', content=AsyncGen()) + request = HttpRequest('GET', 'http://localhost:{}/basic/anything'.format(port), content=AsyncGen()) response = await client.send_request(request) assert response.json()['data'] == "azerty" @pytest.mark.trio async def test_send_data(port): async with TrioRequestsTransport() as transport: - request = HttpRequest('PUT', 'http://httpbin.org/anything', content=b"azerty") + request = HttpRequest('PUT', 'http://localhost:{}/basic/anything'.format(port), content=b"azerty") client = AsyncTestRestClient(port, transport=transport) response = await client.send_request(request) - assert response.json()['data'] == "azerty" \ No newline at end of file + assert response.json()['data'] == "azerty" diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_testserver_async.py b/sdk/core/azure-core/tests/async_tests/test_testserver_async.py similarity index 97% rename from sdk/core/azure-core/tests/testserver_tests/async_tests/test_testserver_async.py rename to sdk/core/azure-core/tests/async_tests/test_testserver_async.py index 623033080bd1..4501e2dc3887 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_testserver_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_testserver_async.py @@ -34,4 +34,4 @@ async def test_smoke(port): response = await sender.send(request) response.raise_for_status() await response.load_body() - assert response.text() == "Hello, world!" \ No newline at end of file + assert response.text() == "Hello, world!" diff --git a/sdk/core/azure-core/tests/async_tests/test_universal_http_async.py b/sdk/core/azure-core/tests/async_tests/test_universal_http_async.py index f6c27b18cabd..2c5944c832fa 100644 --- a/sdk/core/azure-core/tests/async_tests/test_universal_http_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_universal_http_async.py @@ -23,13 +23,10 @@ # THE SOFTWARE. # #-------------------------------------------------------------------------- -import sys - from azure.core.pipeline.transport import ( HttpRequest, AioHttpTransport, AioHttpTransportResponse, - AsyncHttpTransport, AsyncioRequestsTransport, TrioRequestsTransport) @@ -37,7 +34,6 @@ import trio import pytest -from unittest import mock def _create_aiohttp_response(body_bytes, headers=None): @@ -117,4 +113,55 @@ def test_repr(): ) res.content_type = "text/plain" - assert repr(res) == "" \ No newline at end of file + assert repr(res) == "" + +@pytest.mark.asyncio +async def test_basic_aiohttp(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + async with AioHttpTransport() as sender: + response = await sender.send(request) + assert response.body() is not None + + assert sender.session is None + assert isinstance(response.status_code, int) + +@pytest.mark.asyncio +async def test_aiohttp_auto_headers(port): + + request = HttpRequest("POST", "http://localhost:{}/basic/string".format(port)) + async with AioHttpTransport() as sender: + response = await sender.send(request) + auto_headers = response.internal_response.request_info.headers + assert 'Content-Type' not in auto_headers + +@pytest.mark.asyncio +async def test_basic_async_requests(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + async with AsyncioRequestsTransport() as sender: + response = await sender.send(request) + assert response.body() is not None + + assert isinstance(response.status_code, int) + +@pytest.mark.asyncio +async def test_conf_async_requests(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + async with AsyncioRequestsTransport() as sender: + response = await sender.send(request) + assert response.body() is not None + + assert isinstance(response.status_code, int) + +def test_conf_async_trio_requests(port): + + async def do(): + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + async with TrioRequestsTransport() as sender: + return await sender.send(request) + assert response.body() is not None + + response = trio.run(do) + assert isinstance(response.status_code, int) diff --git a/sdk/core/azure-core/tests/conftest.py b/sdk/core/azure-core/tests/conftest.py index 0c5e14c094c7..eaca5b86a530 100644 --- a/sdk/core/azure-core/tests/conftest.py +++ b/sdk/core/azure-core/tests/conftest.py @@ -23,6 +23,14 @@ # IN THE SOFTWARE. # # -------------------------------------------------------------------------- +import time +import pytest +import signal +import os +import subprocess +import random +from six.moves import urllib +from rest_client import TestRestClient import sys # Ignore collection of async tests for Python 2 @@ -39,3 +47,57 @@ Tracer() except ImportError: pass + +def is_port_available(port_num): + req = urllib.request.Request("http://localhost:{}/health".format(port_num)) + try: + return urllib.request.urlopen(req).code != 200 + except Exception as e: + return True + +def get_port(): + count = 3 + for _ in range(count): + port_num = random.randrange(3000, 5000) + if is_port_available(port_num): + return port_num + raise TypeError("Tried {} times, can't find an open port".format(count)) + +@pytest.fixture +def port(): + return os.environ["FLASK_PORT"] + +def start_testserver(): + port = get_port() + os.environ["FLASK_APP"] = "coretestserver" + os.environ["FLASK_PORT"] = str(port) + # os.environ["FLASK_PORT"] = str(port) + cmd = "flask run -p {}".format(port) + if os.name == 'nt': #On windows, subprocess creation works without being in the shell + child_process = subprocess.Popen(cmd, env=dict(os.environ)) + else: + #On linux, have to set shell=True + child_process = subprocess.Popen(cmd, shell=True, preexec_fn=os.setsid, env=dict(os.environ)) + count = 5 + for _ in range(count): + if not is_port_available(port): + return child_process + time.sleep(1) + raise ValueError("Didn't start!") + +def terminate_testserver(process): + if os.name == 'nt': + process.kill() + else: + os.killpg(os.getpgid(process.pid), signal.SIGTERM) # Send the signal to all the process groups + +@pytest.fixture(autouse=True, scope="package") +def testserver(): + """Start the Autorest testserver.""" + server = start_testserver() + yield + terminate_testserver(server) + +@pytest.fixture +def client(port): + return TestRestClient(port) diff --git a/sdk/core/azure-core/tests/testserver_tests/rest_client.py b/sdk/core/azure-core/tests/rest_client.py similarity index 99% rename from sdk/core/azure-core/tests/testserver_tests/rest_client.py rename to sdk/core/azure-core/tests/rest_client.py index 2d896ac3b6aa..0589ab1bf6bd 100644 --- a/sdk/core/azure-core/tests/testserver_tests/rest_client.py +++ b/sdk/core/azure-core/tests/rest_client.py @@ -80,4 +80,4 @@ def send_request(self, request, **kwargs): """ request_copy = deepcopy(request) request_copy.url = self._client.format_url(request_copy.url) - return self._client.send_request(request_copy, **kwargs) \ No newline at end of file + return self._client.send_request(request_copy, **kwargs) diff --git a/sdk/core/azure-core/tests/test_basic_transport.py b/sdk/core/azure-core/tests/test_basic_transport.py index 0f3c9f754b4d..7c57f53dfeee 100644 --- a/sdk/core/azure-core/tests/test_basic_transport.py +++ b/sdk/core/azure-core/tests/test_basic_transport.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See LICENSE.txt in the project root for # license information. # ------------------------------------------------------------------------- +from six.moves.http_client import HTTPConnection from collections import OrderedDict import sys @@ -12,10 +13,11 @@ import mock from azure.core.pipeline.transport import HttpRequest, HttpResponse, RequestsTransport -from azure.core.pipeline.transport._base import HttpTransport, _deserialize_response, _urljoin +from azure.core.pipeline.transport._base import HttpClientTransportResponse, HttpTransport, _deserialize_response, _urljoin from azure.core.pipeline.policies import HeadersPolicy from azure.core.pipeline import Pipeline from azure.core.exceptions import HttpResponseError +import logging import pytest @@ -92,6 +94,27 @@ def test_url_join(): assert _urljoin('devstoreaccount1/', 'testdir/') == 'devstoreaccount1/testdir/' +def test_http_client_response(port): + # Create a core request + request = HttpRequest("GET", "http://localhost:{}".format(port)) + + # Fake a transport based on http.client + conn = HTTPConnection("localhost", port) + conn.request("GET", "/get") + r1 = conn.getresponse() + + response = HttpClientTransportResponse(request, r1) + + # Don't assume too much in those assert, since we reach a real server + assert response.internal_response is r1 + assert response.reason is not None + assert isinstance(response.status_code, int) + assert len(response.headers.keys()) != 0 + assert len(response.text()) != 0 + assert "content-type" in response.headers + assert "Content-Type" in response.headers + + def test_response_deserialization(): # Method + Url @@ -1084,6 +1107,40 @@ def test_close_unopened_transport(): transport.close() +def test_timeout(caplog, port): + transport = RequestsTransport() + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + + with caplog.at_level(logging.WARNING, logger="azure.core.pipeline.transport"): + with Pipeline(transport) as pipeline: + pipeline.run(request, connection_timeout=100) + + assert "Tuple timeout setting is deprecated" not in caplog.text + + +def test_tuple_timeout(caplog, port): + transport = RequestsTransport() + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + + with caplog.at_level(logging.WARNING, logger="azure.core.pipeline.transport"): + with Pipeline(transport) as pipeline: + pipeline.run(request, connection_timeout=(100, 100)) + + assert "Tuple timeout setting is deprecated" in caplog.text + + +def test_conflict_timeout(caplog, port): + transport = RequestsTransport() + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + + with pytest.raises(ValueError): + with Pipeline(transport) as pipeline: + pipeline.run(request, connection_timeout=(100, 100), read_timeout = 100) + + @pytest.mark.skipif(sys.version_info < (3, 10), reason="Loop parameter is deprecated since Python 3.10") def test_aiohttp_loop(): import asyncio diff --git a/sdk/core/azure-core/tests/test_exceptions.py b/sdk/core/azure-core/tests/test_exceptions.py index 7b2bf3ee76d8..2fec2676989d 100644 --- a/sdk/core/azure-core/tests/test_exceptions.py +++ b/sdk/core/azure-core/tests/test_exceptions.py @@ -24,6 +24,7 @@ # # -------------------------------------------------------------------------- import json +import requests try: from unittest.mock import Mock except ImportError: @@ -32,6 +33,7 @@ # module under test from azure.core.exceptions import HttpResponseError, ODataV4Error, ODataV4Format +from azure.core.pipeline.transport import RequestsTransportResponse from azure.core.pipeline.transport._base import _HttpResponseBase @@ -153,6 +155,18 @@ def test_deserialized_httpresponse_error_message(self): assert isinstance(error.model, FakeErrorTwo) assert isinstance(error.error, ODataV4Format) + class TestExceptions(object): + def test_httpresponse_error_with_response(self, port): + response = requests.get("http://localhost:{}/basic/string".format(port)) + http_response = RequestsTransportResponse(None, response) + + error = HttpResponseError(response=http_response) + assert error.message == "Operation returned an invalid status 'OK'" + assert error.response is not None + assert error.reason == 'OK' + assert isinstance(error.status_code, int) + assert error.error is None + def test_odata_v4_exception(self): message = { "error": { diff --git a/sdk/core/azure-core/tests/test_pipeline.py b/sdk/core/azure-core/tests/test_pipeline.py index e056d18350ee..6d260c07e9fe 100644 --- a/sdk/core/azure-core/tests/test_pipeline.py +++ b/sdk/core/azure-core/tests/test_pipeline.py @@ -354,3 +354,67 @@ def send(*args): client = PipelineClient(base_url="test", policies=policies, per_retry_policies=foo_policy) with pytest.raises(ValueError): client = PipelineClient(base_url="test", policies=policies, per_retry_policies=[foo_policy]) + +def test_basic_requests(port): + + conf = Configuration() + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + RedirectPolicy() + ] + with Pipeline(RequestsTransport(), policies=policies) as pipeline: + response = pipeline.run(request) + + assert pipeline._transport.session is None + assert isinstance(response.http_response.status_code, int) + +def test_basic_options_requests(port): + + request = HttpRequest("OPTIONS", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + RedirectPolicy() + ] + with Pipeline(RequestsTransport(), policies=policies) as pipeline: + response = pipeline.run(request) + + assert pipeline._transport.session is None + assert isinstance(response.http_response.status_code, int) + +def test_basic_requests_separate_session(port): + + session = requests.Session() + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + RedirectPolicy() + ] + transport = RequestsTransport(session=session, session_owner=False) + with Pipeline(transport, policies=policies) as pipeline: + response = pipeline.run(request) + + assert transport.session + assert isinstance(response.http_response.status_code, int) + transport.close() + assert transport.session + transport.session.close() + +def test_request_text(port): + client = PipelineClientBase("http://localhost:{}".format(port)) + request = client.get( + "/", + content="foo" + ) + + # In absence of information, everything is JSON (double quote added) + assert request.data == json.dumps("foo") + + request = client.post( + "/", + headers={'content-type': 'text/whatever'}, + content="foo" + ) + + # We want a direct string + assert request.data == "foo" diff --git a/sdk/core/azure-core/tests/test_requests_universal.py b/sdk/core/azure-core/tests/test_requests_universal.py index b599586993ee..b965d4fd3d69 100644 --- a/sdk/core/azure-core/tests/test_requests_universal.py +++ b/sdk/core/azure-core/tests/test_requests_universal.py @@ -24,10 +24,9 @@ # # -------------------------------------------------------------------------- import concurrent.futures -import pytest import requests.utils -from azure.core.pipeline.transport import RequestsTransport, RequestsTransportResponse +from azure.core.pipeline.transport import HttpRequest, RequestsTransport, RequestsTransportResponse def test_threading_basic_requests(): @@ -45,6 +44,12 @@ def thread_body(local_sender): future = executor.submit(thread_body, sender) assert future.result() +def test_requests_auto_headers(port): + request = HttpRequest("POST", "http://localhost:{}/basic/string".format(port)) + with RequestsTransport() as sender: + response = sender.send(request) + auto_headers = response.internal_response.request.headers + assert 'Content-Type' not in auto_headers def _create_requests_response(body_bytes, headers=None): # https://github.com/psf/requests/blob/67a7b2e8336951d527e223429672354989384197/requests/adapters.py#L255 diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_context_manager.py b/sdk/core/azure-core/tests/test_rest_context_manager.py similarity index 100% rename from sdk/core/azure-core/tests/testserver_tests/test_rest_context_manager.py rename to sdk/core/azure-core/tests/test_rest_context_manager.py diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_headers.py b/sdk/core/azure-core/tests/test_rest_headers.py similarity index 100% rename from sdk/core/azure-core/tests/testserver_tests/test_rest_headers.py rename to sdk/core/azure-core/tests/test_rest_headers.py diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_request.py b/sdk/core/azure-core/tests/test_rest_http_request.py similarity index 99% rename from sdk/core/azure-core/tests/testserver_tests/test_rest_http_request.py rename to sdk/core/azure-core/tests/test_rest_http_request.py index e0ae70642431..92347f9247a3 100644 --- a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_request.py +++ b/sdk/core/azure-core/tests/test_rest_http_request.py @@ -11,7 +11,6 @@ import pytest import sys import collections -from typing import Generator from azure.core.rest import HttpRequest @pytest.fixture diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py b/sdk/core/azure-core/tests/test_rest_http_response.py similarity index 100% rename from sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py rename to sdk/core/azure-core/tests/test_rest_http_response.py diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_query.py b/sdk/core/azure-core/tests/test_rest_query.py similarity index 99% rename from sdk/core/azure-core/tests/testserver_tests/test_rest_query.py rename to sdk/core/azure-core/tests/test_rest_query.py index 7933e998f1e6..7aeda360da6a 100644 --- a/sdk/core/azure-core/tests/testserver_tests/test_rest_query.py +++ b/sdk/core/azure-core/tests/test_rest_query.py @@ -28,4 +28,4 @@ def test_request_url_with_params_with_none_in_list(): def test_request_url_with_params_with_none(): with pytest.raises(ValueError): - _format_query_into_url(url="a/b/c?t=y", params={"g": None}) \ No newline at end of file + _format_query_into_url(url="a/b/c?t=y", params={"g": None}) diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_stream_responses.py b/sdk/core/azure-core/tests/test_rest_stream_responses.py similarity index 100% rename from sdk/core/azure-core/tests/testserver_tests/test_rest_stream_responses.py rename to sdk/core/azure-core/tests/test_rest_stream_responses.py diff --git a/sdk/core/azure-core/tests/testserver_tests/test_testserver.py b/sdk/core/azure-core/tests/test_testserver.py similarity index 99% rename from sdk/core/azure-core/tests/testserver_tests/test_testserver.py rename to sdk/core/azure-core/tests/test_testserver.py index a31d449fbd53..0cf5e4ffc26e 100644 --- a/sdk/core/azure-core/tests/testserver_tests/test_testserver.py +++ b/sdk/core/azure-core/tests/test_testserver.py @@ -23,7 +23,6 @@ # THE SOFTWARE. # # -------------------------------------------------------------------------- -import pytest from azure.core.pipeline.transport import HttpRequest, RequestsTransport """This file does a simple call to the testserver to make sure we can use the testserver""" diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_basic_transport_async_test_server.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_basic_transport_async_test_server.py deleted file mode 100644 index d96cb4d23ec8..000000000000 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_basic_transport_async_test_server.py +++ /dev/null @@ -1,22 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See LICENSE.txt in the project root for -# license information. -# ------------------------------------------------------------------------- -from six.moves.http_client import HTTPConnection -import time - -from azure.core.pipeline.transport import HttpRequest, AioHttpTransport -from azure.core.pipeline import AsyncPipeline - -import pytest - -@pytest.mark.asyncio -async def test_basic_options_aiohttp(port): - - request = HttpRequest("OPTIONS", "http://localhost:{}/basic/string".format(port)) - async with AsyncPipeline(AioHttpTransport(), policies=[]) as pipeline: - response = await pipeline.run(request) - - assert pipeline._transport.session is None - assert isinstance(response.http_response.status_code, int) diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_pipeline_async_test_server.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_pipeline_async_test_server.py deleted file mode 100644 index 7304ae90874e..000000000000 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_pipeline_async_test_server.py +++ /dev/null @@ -1,118 +0,0 @@ -#-------------------------------------------------------------------------- -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -#-------------------------------------------------------------------------- -import sys - -from azure.core.pipeline import AsyncPipeline -from azure.core.pipeline.policies import ( - UserAgentPolicy, - AsyncRedirectPolicy, -) -from azure.core.pipeline.transport import ( - HttpRequest, - AsyncioRequestsTransport, - TrioRequestsTransport, - AioHttpTransport -) - -import aiohttp -import trio - -import pytest - - -@pytest.mark.asyncio -async def test_basic_aiohttp(port): - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - async with AsyncPipeline(AioHttpTransport(), policies=policies) as pipeline: - response = await pipeline.run(request) - - assert pipeline._transport.session is None - # all we need to check is if we are able to make the call - assert isinstance(response.http_response.status_code, int) - -@pytest.mark.asyncio -async def test_basic_aiohttp_separate_session(port): - - session = aiohttp.ClientSession() - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - transport = AioHttpTransport(session=session, session_owner=False) - async with AsyncPipeline(transport, policies=policies) as pipeline: - response = await pipeline.run(request) - - assert transport.session - assert isinstance(response.http_response.status_code, int) - await transport.close() - assert transport.session - await transport.session.close() - -@pytest.mark.asyncio -async def test_basic_async_requests(port): - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - async with AsyncPipeline(AsyncioRequestsTransport(), policies=policies) as pipeline: - response = await pipeline.run(request) - - assert isinstance(response.http_response.status_code, int) - -@pytest.mark.asyncio -async def test_conf_async_requests(port): - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - async with AsyncPipeline(AsyncioRequestsTransport(), policies=policies) as pipeline: - response = await pipeline.run(request) - - assert isinstance(response.http_response.status_code, int) - -def test_conf_async_trio_requests(port): - - async def do(): - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - async with AsyncPipeline(TrioRequestsTransport(), policies=policies) as pipeline: - return await pipeline.run(request) - - response = trio.run(do) - assert isinstance(response.http_response.status_code, int) diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_universal_http_async_test_server.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_universal_http_async_test_server.py deleted file mode 100644 index d4c376ed3241..000000000000 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_universal_http_async_test_server.py +++ /dev/null @@ -1,89 +0,0 @@ -#-------------------------------------------------------------------------- -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -#-------------------------------------------------------------------------- -import sys - -from azure.core.pipeline.transport import ( - HttpRequest, - AioHttpTransport, - AsyncioRequestsTransport, - TrioRequestsTransport -) - -import trio - -import pytest - - -@pytest.mark.asyncio -async def test_basic_aiohttp(port): - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - async with AioHttpTransport() as sender: - response = await sender.send(request) - assert response.body() is not None - - assert sender.session is None - assert isinstance(response.status_code, int) - -@pytest.mark.asyncio -async def test_aiohttp_auto_headers(port): - - request = HttpRequest("POST", "http://localhost:{}/basic/string".format(port)) - async with AioHttpTransport() as sender: - response = await sender.send(request) - auto_headers = response.internal_response.request_info.headers - assert 'Content-Type' not in auto_headers - -@pytest.mark.asyncio -async def test_basic_async_requests(port): - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - async with AsyncioRequestsTransport() as sender: - response = await sender.send(request) - assert response.body() is not None - - assert isinstance(response.status_code, int) - -@pytest.mark.asyncio -async def test_conf_async_requests(port): - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - async with AsyncioRequestsTransport() as sender: - response = await sender.send(request) - assert response.body() is not None - - assert isinstance(response.status_code, int) - -def test_conf_async_trio_requests(port): - - async def do(): - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - async with TrioRequestsTransport() as sender: - return await sender.send(request) - assert response.body() is not None - - response = trio.run(do) - assert isinstance(response.status_code, int) diff --git a/sdk/core/azure-core/tests/testserver_tests/conftest.py b/sdk/core/azure-core/tests/testserver_tests/conftest.py deleted file mode 100644 index 422904288fd1..000000000000 --- a/sdk/core/azure-core/tests/testserver_tests/conftest.py +++ /dev/null @@ -1,92 +0,0 @@ -# -------------------------------------------------------------------------- -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -# -------------------------------------------------------------------------- -import time -import pytest -import signal -import os -import subprocess -import random -from six.moves import urllib -from rest_client import TestRestClient -import sys - -# Ignore collection of async tests for Python 2 -collect_ignore = [] -if sys.version_info < (3, 5): - collect_ignore.append("async_tests") - -def is_port_available(port_num): - req = urllib.request.Request("http://localhost:{}/health".format(port_num)) - try: - return urllib.request.urlopen(req).code != 200 - except Exception as e: - return True - -def get_port(): - count = 3 - for _ in range(count): - port_num = random.randrange(3000, 5000) - if is_port_available(port_num): - return port_num - raise TypeError("Tried {} times, can't find an open port".format(count)) - -@pytest.fixture -def port(): - return os.environ["FLASK_PORT"] - -def start_testserver(): - port = get_port() - os.environ["FLASK_APP"] = "coretestserver" - os.environ["FLASK_PORT"] = str(port) - cmd = "flask run -p {}".format(port) - if os.name == 'nt': #On windows, subprocess creation works without being in the shell - child_process = subprocess.Popen(cmd, env=dict(os.environ)) - else: - #On linux, have to set shell=True - child_process = subprocess.Popen(cmd, shell=True, preexec_fn=os.setsid, env=dict(os.environ)) - count = 5 - for _ in range(count): - if not is_port_available(port): - return child_process - time.sleep(1) - raise ValueError("Didn't start!") - -def terminate_testserver(process): - if os.name == 'nt': - process.kill() - else: - os.killpg(os.getpgid(process.pid), signal.SIGTERM) # Send the signal to all the process groups - -@pytest.fixture(autouse=True, scope="package") -def testserver(): - """Start the Autorest testserver.""" - server = start_testserver() - yield - terminate_testserver(server) - -@pytest.fixture -def client(port): - return TestRestClient(port) diff --git a/sdk/core/azure-core/tests/testserver_tests/coretestserver/coretestserver/test_routes/basic.py b/sdk/core/azure-core/tests/testserver_tests/coretestserver/coretestserver/test_routes/basic.py index 933a53de5d14..86117c112810 100644 --- a/sdk/core/azure-core/tests/testserver_tests/coretestserver/coretestserver/test_routes/basic.py +++ b/sdk/core/azure-core/tests/testserver_tests/coretestserver/coretestserver/test_routes/basic.py @@ -8,8 +8,9 @@ from flask import ( Response, Blueprint, - request + request, ) +from .helpers import jsonify, get_dict basic_api = Blueprint('basic_api', __name__) @@ -75,3 +76,19 @@ def headers(): "CamelCase-Header": "camelCase", } ) + +@basic_api.route("/anything", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "TRACE"]) +def anything(): + return jsonify( + get_dict( + "url", + "args", + "headers", + "origin", + "method", + "form", + "data", + "files", + "json", + ) + ) diff --git a/sdk/core/azure-core/tests/testserver_tests/coretestserver/coretestserver/test_routes/helpers.py b/sdk/core/azure-core/tests/testserver_tests/coretestserver/coretestserver/test_routes/helpers.py index 46680f65d3f9..f541d4be27c1 100644 --- a/sdk/core/azure-core/tests/testserver_tests/coretestserver/coretestserver/test_routes/helpers.py +++ b/sdk/core/azure-core/tests/testserver_tests/coretestserver/coretestserver/test_routes/helpers.py @@ -3,10 +3,161 @@ # Licensed under the MIT License. See LICENSE.txt in the project root for # license information. # ------------------------------------------------------------------------- +from flask import ( + request, + jsonify as flask_jsonify, +) +from six.moves.urllib.parse import urlparse, urlunparse +from .structures import CaseInsensitiveDict +import json + +ENV_HEADERS = ( + 'X-Varnish', + 'X-Request-Start', + 'X-Heroku-Queue-Depth', + 'X-Real-Ip', + 'X-Forwarded-Proto', + 'X-Forwarded-Protocol', + 'X-Forwarded-Ssl', + 'X-Heroku-Queue-Wait-Time', + 'X-Forwarded-For', + 'X-Heroku-Dynos-In-Use', + 'X-Forwarded-Protocol', + 'X-Forwarded-Port', + 'X-Request-Id', + 'Via', + 'Total-Route-Time', + 'Connect-Time' +) def assert_with_message(param_name, expected_value, actual_value): assert expected_value == actual_value, "Expected '{}' to be '{}', got '{}'".format( param_name, expected_value, actual_value ) -__all__ = ["assert_with_message"] +def jsonify(*args, **kwargs): + response = flask_jsonify(*args, **kwargs) + if not response.data.endswith(b"\n"): + response.data += b"\n" + return response + +def get_url(request): + """ + Since we might be hosted behind a proxy, we need to check the + X-Forwarded-Proto, X-Forwarded-Protocol, or X-Forwarded-SSL headers + to find out what protocol was used to access us. + """ + protocol = request.headers.get('X-Forwarded-Proto') or request.headers.get('X-Forwarded-Protocol') + if protocol is None and request.headers.get('X-Forwarded-Ssl') == 'on': + protocol = 'https' + if protocol is None: + return request.url + url = list(urlparse(request.url)) + url[0] = protocol + return urlunparse(url) + +def get_files(): + """Returns files dict from request context.""" + + files = dict() + + for k, v in request.files.items(): + content_type = request.files[k].content_type or 'application/octet-stream' + val = json_safe(v.read(), content_type) + if files.get(k): + if not isinstance(files[k], list): + files[k] = [files[k]] + files[k].append(val) + else: + files[k] = val + + return files + +def get_headers(hide_env=True): + """Returns headers dict from request context.""" + + headers = dict(request.headers.items()) + + if hide_env and ('show_env' not in request.args): + for key in ENV_HEADERS: + try: + del headers[key] + except KeyError: + pass + + return CaseInsensitiveDict(headers.items()) + +def semiflatten(multi): + """Convert a MutiDict into a regular dict. If there are more than one value + for a key, the result will have a list of values for the key. Otherwise it + will have the plain value.""" + if multi: + result = multi.to_dict(flat=False) + for k, v in result.items(): + if len(v) == 1: + result[k] = v[0] + return result + else: + return multi + +def json_safe(string, content_type='application/octet-stream'): + """Returns JSON-safe version of `string`. + + If `string` is a Unicode string or a valid UTF-8, it is returned unmodified, + as it can safely be encoded to JSON string. + + If `string` contains raw/binary data, it is Base64-encoded, formatted and + returned according to "data" URL scheme (RFC2397). Since JSON is not + suitable for binary data, some additional encoding was necessary; "data" + URL scheme was chosen for its simplicity. + """ + try: + string = string.decode('utf-8') + json.dumps(string) + return string + except (ValueError, TypeError): + return b''.join([ + b'data:', + content_type.encode('utf-8'), + b';base64,', + base64.b64encode(string) + ]).decode('utf-8') + +def get_dict(*keys, **extras): + """Returns request dict of given keys.""" + + _keys = ('url', 'args', 'form', 'data', 'origin', 'headers', 'files', 'json', 'method') + + assert all(map(_keys.__contains__, keys)) + data = request.data + form = semiflatten(request.form) + + try: + _json = json.loads(data.decode('utf-8')) + except (ValueError, TypeError): + _json = None + + d = dict( + url=get_url(request), + args=semiflatten(request.args), + form=form, + data=json_safe(data), + origin=request.headers.get('X-Forwarded-For', request.remote_addr), + headers=get_headers(), + files=get_files(), + json=_json, + method=request.method, + ) + + out_d = dict() + + for key in keys: + out_d[key] = d.get(key) + + out_d.update(extras) + + return out_d + +__all__ = ["assert_with_message", + "get_dict", + "jsonify"] \ No newline at end of file diff --git a/sdk/core/azure-core/tests/testserver_tests/coretestserver/coretestserver/test_routes/structures.py b/sdk/core/azure-core/tests/testserver_tests/coretestserver/coretestserver/test_routes/structures.py new file mode 100644 index 000000000000..1e443986cdf2 --- /dev/null +++ b/sdk/core/azure-core/tests/testserver_tests/coretestserver/coretestserver/test_routes/structures.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + +class CaseInsensitiveDict(dict): + """Case-insensitive Dictionary for headers. + + For example, ``headers['content-encoding']`` will return the + value of a ``'Content-Encoding'`` response header. + """ + + def _lower_keys(self): + return [k.lower() for k in self.keys()] + + def __contains__(self, key): + return key.lower() in self._lower_keys() + + def __getitem__(self, key): + # We allow fall-through here, so values default to None + if key in self: + return list(self.items())[self._lower_keys().index(key.lower())][1] diff --git a/sdk/core/azure-core/tests/testserver_tests/test_basic_transport_test_server.py b/sdk/core/azure-core/tests/testserver_tests/test_basic_transport_test_server.py deleted file mode 100644 index cb74af191ea5..000000000000 --- a/sdk/core/azure-core/tests/testserver_tests/test_basic_transport_test_server.py +++ /dev/null @@ -1,66 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See LICENSE.txt in the project root for -# license information. -# ------------------------------------------------------------------------- -from six.moves.http_client import HTTPConnection -from azure.core.pipeline.transport import HttpRequest, RequestsTransport -from azure.core.pipeline.transport._base import HttpClientTransportResponse -from azure.core.pipeline import Pipeline -import logging -import pytest - - -def test_http_client_response(port): - # Create a core request - request = HttpRequest("GET", "http://localhost:{}".format(port)) - - # Fake a transport based on http.client - conn = HTTPConnection("localhost", port) - conn.request("GET", "/get") - r1 = conn.getresponse() - - response = HttpClientTransportResponse(request, r1) - - # Don't assume too much in those assert, since we reach a real server - assert response.internal_response is r1 - assert response.reason is not None - assert isinstance(response.status_code, int) - assert len(response.headers.keys()) != 0 - assert len(response.text()) != 0 - assert "content-type" in response.headers - assert "Content-Type" in response.headers - - -def test_timeout(caplog, port): - transport = RequestsTransport() - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - - with caplog.at_level(logging.WARNING, logger="azure.core.pipeline.transport"): - with Pipeline(transport) as pipeline: - pipeline.run(request, connection_timeout=100) - - assert "Tuple timeout setting is deprecated" not in caplog.text - - -def test_tuple_timeout(caplog, port): - transport = RequestsTransport() - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - - with caplog.at_level(logging.WARNING, logger="azure.core.pipeline.transport"): - with Pipeline(transport) as pipeline: - pipeline.run(request, connection_timeout=(100, 100)) - - assert "Tuple timeout setting is deprecated" in caplog.text - - -def test_conflict_timeout(caplog, port): - transport = RequestsTransport() - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - - with pytest.raises(ValueError): - with Pipeline(transport) as pipeline: - pipeline.run(request, connection_timeout=(100, 100), read_timeout = 100) diff --git a/sdk/core/azure-core/tests/testserver_tests/test_exceptions_test_server.py b/sdk/core/azure-core/tests/testserver_tests/test_exceptions_test_server.py deleted file mode 100644 index 6dd95c47f90c..000000000000 --- a/sdk/core/azure-core/tests/testserver_tests/test_exceptions_test_server.py +++ /dev/null @@ -1,40 +0,0 @@ -# -------------------------------------------------------------------------- -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -# -------------------------------------------------------------------------- -import requests -from azure.core.exceptions import HttpResponseError -from azure.core.pipeline.transport import RequestsTransportResponse - -class TestExceptions(object): - def test_httpresponse_error_with_response(self, port): - response = requests.get("http://localhost:{}/basic/string".format(port)) - http_response = RequestsTransportResponse(None, response) - - error = HttpResponseError(response=http_response) - assert error.message == "Operation returned an invalid status 'OK'" - assert error.response is not None - assert error.reason == 'OK' - assert isinstance(error.status_code, int) - assert error.error is None diff --git a/sdk/core/azure-core/tests/testserver_tests/test_pipeline_test_server.py b/sdk/core/azure-core/tests/testserver_tests/test_pipeline_test_server.py deleted file mode 100644 index d5c503a39fa3..000000000000 --- a/sdk/core/azure-core/tests/testserver_tests/test_pipeline_test_server.py +++ /dev/null @@ -1,105 +0,0 @@ -# -------------------------------------------------------------------------- -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -# -------------------------------------------------------------------------- - -import json -import requests - -from azure.core.configuration import Configuration -from azure.core.pipeline import Pipeline -from azure.core.pipeline.policies import ( - UserAgentPolicy, - RedirectPolicy, -) -from azure.core.pipeline.transport._base import PipelineClientBase -from azure.core.pipeline.transport import ( - HttpRequest, - RequestsTransport, -) - - -def test_basic_requests(port): - - conf = Configuration() - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - RedirectPolicy() - ] - with Pipeline(RequestsTransport(), policies=policies) as pipeline: - response = pipeline.run(request) - - assert pipeline._transport.session is None - assert isinstance(response.http_response.status_code, int) - -def test_basic_options_requests(port): - - request = HttpRequest("OPTIONS", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - RedirectPolicy() - ] - with Pipeline(RequestsTransport(), policies=policies) as pipeline: - response = pipeline.run(request) - - assert pipeline._transport.session is None - assert isinstance(response.http_response.status_code, int) - -def test_basic_requests_separate_session(port): - - session = requests.Session() - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - RedirectPolicy() - ] - transport = RequestsTransport(session=session, session_owner=False) - with Pipeline(transport, policies=policies) as pipeline: - response = pipeline.run(request) - - assert transport.session - assert isinstance(response.http_response.status_code, int) - transport.close() - assert transport.session - transport.session.close() - -def test_request_text(port): - client = PipelineClientBase("http://localhost:{}".format(port)) - request = client.get( - "/", - content="foo" - ) - - # In absence of information, everything is JSON (double quote added) - assert request.data == json.dumps("foo") - - request = client.post( - "/", - headers={'content-type': 'text/whatever'}, - content="foo" - ) - - # We want a direct string - assert request.data == "foo" diff --git a/sdk/core/azure-core/tests/testserver_tests/test_requests_universal_test_server.py b/sdk/core/azure-core/tests/testserver_tests/test_requests_universal_test_server.py deleted file mode 100644 index 85f0e955a0e0..000000000000 --- a/sdk/core/azure-core/tests/testserver_tests/test_requests_universal_test_server.py +++ /dev/null @@ -1,33 +0,0 @@ -# -------------------------------------------------------------------------- -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -# -------------------------------------------------------------------------- -from azure.core.pipeline.transport import HttpRequest, RequestsTransport - -def test_requests_auto_headers(port): - request = HttpRequest("POST", "http://localhost:{}/basic/string".format(port)) - with RequestsTransport() as sender: - response = sender.send(request) - auto_headers = response.internal_response.request.headers - assert 'Content-Type' not in auto_headers From 84519b4974cdc7e0af4bdcc9a4457551f217850f Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Thu, 19 Aug 2021 13:10:43 -0700 Subject: [PATCH 5/6] update --- .../async_tests/test_basic_transport_async.py | 21 +-- .../tests/async_tests/test_pipeline_async.py | 148 +++++++++--------- .../tests/async_tests/test_request_asyncio.py | 2 - .../async_tests/test_universal_http_async.py | 103 ++++++------ sdk/core/azure-core/tests/test_exceptions.py | 21 ++- 5 files changed, 147 insertions(+), 148 deletions(-) diff --git a/sdk/core/azure-core/tests/async_tests/test_basic_transport_async.py b/sdk/core/azure-core/tests/async_tests/test_basic_transport_async.py index 75a8ce4d8e9f..1ae80db6f60c 100644 --- a/sdk/core/azure-core/tests/async_tests/test_basic_transport_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_basic_transport_async.py @@ -33,6 +33,17 @@ def body(self): return self._body +@pytest.mark.asyncio +async def test_basic_options_aiohttp(port): + + request = HttpRequest("OPTIONS", "http://localhost:{}/basic/string".format(port)) + async with AsyncPipeline(AioHttpTransport(), policies=[]) as pipeline: + response = await pipeline.run(request) + + assert pipeline._transport.session is None + assert isinstance(response.http_response.status_code, int) + + @pytest.mark.asyncio async def test_multipart_send(): transport = MockAsyncHttpTransport() @@ -925,13 +936,3 @@ async def test_recursive_multipart_receive(): internal_response0 = internal_parts[0] assert internal_response0.status_code == 400 - -@pytest.mark.asyncio -async def test_basic_options_aiohttp(port): - - request = HttpRequest("OPTIONS", "http://localhost:{}/basic/string".format(port)) - async with AsyncPipeline(AioHttpTransport(), policies=[]) as pipeline: - response = await pipeline.run(request) - - assert pipeline._transport.session is None - assert isinstance(response.http_response.status_code, int) diff --git a/sdk/core/azure-core/tests/async_tests/test_pipeline_async.py b/sdk/core/azure-core/tests/async_tests/test_pipeline_async.py index 17a5ad0248ea..a84d53093ca3 100644 --- a/sdk/core/azure-core/tests/async_tests/test_pipeline_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_pipeline_async.py @@ -88,6 +88,53 @@ def on_exception(self, requests, **kwargs): with pytest.raises(NotImplementedError): await pipeline.run(req) +@pytest.mark.asyncio +async def test_basic_aiohttp(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + async with AsyncPipeline(AioHttpTransport(), policies=policies) as pipeline: + response = await pipeline.run(request) + + assert pipeline._transport.session is None + # all we need to check is if we are able to make the call + assert isinstance(response.http_response.status_code, int) + +@pytest.mark.asyncio +async def test_basic_aiohttp_separate_session(port): + + session = aiohttp.ClientSession() + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + transport = AioHttpTransport(session=session, session_owner=False) + async with AsyncPipeline(transport, policies=policies) as pipeline: + response = await pipeline.run(request) + + assert transport.session + assert isinstance(response.http_response.status_code, int) + await transport.close() + assert transport.session + await transport.session.close() + +@pytest.mark.asyncio +async def test_basic_async_requests(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + async with AsyncPipeline(AsyncioRequestsTransport(), policies=policies) as pipeline: + response = await pipeline.run(request) + + assert isinstance(response.http_response.status_code, int) + @pytest.mark.asyncio async def test_async_transport_sleep(): @@ -137,6 +184,33 @@ def test_pass_in_http_logging_policy(): http_logging_policy = pipeline._impl_policies[-1]._policy assert http_logging_policy.allowed_header_names == HttpLoggingPolicy.DEFAULT_HEADERS_WHITELIST.union({"x-ms-added-header"}) +@pytest.mark.asyncio +async def test_conf_async_requests(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + async with AsyncPipeline(AsyncioRequestsTransport(), policies=policies) as pipeline: + response = await pipeline.run(request) + + assert isinstance(response.http_response.status_code, int) + +def test_conf_async_trio_requests(port): + + async def do(): + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + policies = [ + UserAgentPolicy("myusergant"), + AsyncRedirectPolicy() + ] + async with AsyncPipeline(TrioRequestsTransport(), policies=policies) as pipeline: + return await pipeline.run(request) + + response = trio.run(do) + assert isinstance(response.http_response.status_code, int) + @pytest.mark.asyncio async def test_retry_without_http_response(): class NaughtyPolicy(AsyncHTTPPolicy): @@ -247,77 +321,3 @@ def send(*args): client = AsyncPipelineClient(base_url="test", policies=policies, per_retry_policies=foo_policy) with pytest.raises(ValueError): client = AsyncPipelineClient(base_url="test", policies=policies, per_retry_policies=[foo_policy]) - -@pytest.mark.asyncio -async def test_basic_aiohttp(port): - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - async with AsyncPipeline(AioHttpTransport(), policies=policies) as pipeline: - response = await pipeline.run(request) - - assert pipeline._transport.session is None - # all we need to check is if we are able to make the call - assert isinstance(response.http_response.status_code, int) - -@pytest.mark.asyncio -async def test_basic_aiohttp_separate_session(port): - - session = aiohttp.ClientSession() - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - transport = AioHttpTransport(session=session, session_owner=False) - async with AsyncPipeline(transport, policies=policies) as pipeline: - response = await pipeline.run(request) - - assert transport.session - assert isinstance(response.http_response.status_code, int) - await transport.close() - assert transport.session - await transport.session.close() - -@pytest.mark.asyncio -async def test_basic_async_requests(port): - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - async with AsyncPipeline(AsyncioRequestsTransport(), policies=policies) as pipeline: - response = await pipeline.run(request) - - assert isinstance(response.http_response.status_code, int) - -@pytest.mark.asyncio -async def test_conf_async_requests(port): - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - async with AsyncPipeline(AsyncioRequestsTransport(), policies=policies) as pipeline: - response = await pipeline.run(request) - - assert isinstance(response.http_response.status_code, int) - -def test_conf_async_trio_requests(port): - - async def do(): - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - policies = [ - UserAgentPolicy("myusergant"), - AsyncRedirectPolicy() - ] - async with AsyncPipeline(TrioRequestsTransport(), policies=policies) as pipeline: - return await pipeline.run(request) - - response = trio.run(do) - assert isinstance(response.http_response.status_code, int) diff --git a/sdk/core/azure-core/tests/async_tests/test_request_asyncio.py b/sdk/core/azure-core/tests/async_tests/test_request_asyncio.py index d07b23f29540..55856ae6ca94 100644 --- a/sdk/core/azure-core/tests/async_tests/test_request_asyncio.py +++ b/sdk/core/azure-core/tests/async_tests/test_request_asyncio.py @@ -28,7 +28,6 @@ async def __anext__(self): async with AsyncioRequestsTransport() as transport: req = HttpRequest('GET', 'http://localhost:{}/basic/anything'.format(port), data=AsyncGen()) response = await transport.send(req) - text = response.text() assert json.loads(response.text())['data'] == "azerty" @pytest.mark.asyncio @@ -36,5 +35,4 @@ async def test_send_data(port): async with AsyncioRequestsTransport() as transport: req = HttpRequest('PUT', 'http://localhost:{}/basic/anything'.format(port), data=b"azerty") response = await transport.send(req) - text = response.text() assert json.loads(response.text())['data'] == "azerty" diff --git a/sdk/core/azure-core/tests/async_tests/test_universal_http_async.py b/sdk/core/azure-core/tests/async_tests/test_universal_http_async.py index 2c5944c832fa..fa65fc3353c5 100644 --- a/sdk/core/azure-core/tests/async_tests/test_universal_http_async.py +++ b/sdk/core/azure-core/tests/async_tests/test_universal_http_async.py @@ -36,6 +36,58 @@ import pytest +@pytest.mark.asyncio +async def test_basic_aiohttp(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + async with AioHttpTransport() as sender: + response = await sender.send(request) + assert response.body() is not None + + assert sender.session is None + assert isinstance(response.status_code, int) + +@pytest.mark.asyncio +async def test_aiohttp_auto_headers(port): + + request = HttpRequest("POST", "http://localhost:{}/basic/string".format(port)) + async with AioHttpTransport() as sender: + response = await sender.send(request) + auto_headers = response.internal_response.request_info.headers + assert 'Content-Type' not in auto_headers + +@pytest.mark.asyncio +async def test_basic_async_requests(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + async with AsyncioRequestsTransport() as sender: + response = await sender.send(request) + assert response.body() is not None + + assert isinstance(response.status_code, int) + +@pytest.mark.asyncio +async def test_conf_async_requests(port): + + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + async with AsyncioRequestsTransport() as sender: + response = await sender.send(request) + assert response.body() is not None + + assert isinstance(response.status_code, int) + +def test_conf_async_trio_requests(port): + + async def do(): + request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) + async with TrioRequestsTransport() as sender: + return await sender.send(request) + assert response.body() is not None + + response = trio.run(do) + assert isinstance(response.status_code, int) + + def _create_aiohttp_response(body_bytes, headers=None): class MockAiohttpClientResponse(aiohttp.ClientResponse): def __init__(self, body_bytes, headers=None): @@ -114,54 +166,3 @@ def test_repr(): res.content_type = "text/plain" assert repr(res) == "" - -@pytest.mark.asyncio -async def test_basic_aiohttp(port): - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - async with AioHttpTransport() as sender: - response = await sender.send(request) - assert response.body() is not None - - assert sender.session is None - assert isinstance(response.status_code, int) - -@pytest.mark.asyncio -async def test_aiohttp_auto_headers(port): - - request = HttpRequest("POST", "http://localhost:{}/basic/string".format(port)) - async with AioHttpTransport() as sender: - response = await sender.send(request) - auto_headers = response.internal_response.request_info.headers - assert 'Content-Type' not in auto_headers - -@pytest.mark.asyncio -async def test_basic_async_requests(port): - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - async with AsyncioRequestsTransport() as sender: - response = await sender.send(request) - assert response.body() is not None - - assert isinstance(response.status_code, int) - -@pytest.mark.asyncio -async def test_conf_async_requests(port): - - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - async with AsyncioRequestsTransport() as sender: - response = await sender.send(request) - assert response.body() is not None - - assert isinstance(response.status_code, int) - -def test_conf_async_trio_requests(port): - - async def do(): - request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) - async with TrioRequestsTransport() as sender: - return await sender.send(request) - assert response.body() is not None - - response = trio.run(do) - assert isinstance(response.status_code, int) diff --git a/sdk/core/azure-core/tests/test_exceptions.py b/sdk/core/azure-core/tests/test_exceptions.py index 2fec2676989d..a5d494e559b7 100644 --- a/sdk/core/azure-core/tests/test_exceptions.py +++ b/sdk/core/azure-core/tests/test_exceptions.py @@ -155,17 +155,16 @@ def test_deserialized_httpresponse_error_message(self): assert isinstance(error.model, FakeErrorTwo) assert isinstance(error.error, ODataV4Format) - class TestExceptions(object): - def test_httpresponse_error_with_response(self, port): - response = requests.get("http://localhost:{}/basic/string".format(port)) - http_response = RequestsTransportResponse(None, response) - - error = HttpResponseError(response=http_response) - assert error.message == "Operation returned an invalid status 'OK'" - assert error.response is not None - assert error.reason == 'OK' - assert isinstance(error.status_code, int) - assert error.error is None + def test_httpresponse_error_with_response(self, port): + response = requests.get("http://localhost:{}/basic/string".format(port)) + http_response = RequestsTransportResponse(None, response) + + error = HttpResponseError(response=http_response) + assert error.message == "Operation returned an invalid status 'OK'" + assert error.response is not None + assert error.reason == 'OK' + assert isinstance(error.status_code, int) + assert error.error is None def test_odata_v4_exception(self): message = { From 53a9cce4cd43f4367e99344973551e97d8bd8037 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Thu, 19 Aug 2021 13:28:43 -0700 Subject: [PATCH 6/6] update --- sdk/core/azure-core/tests/conftest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/core/azure-core/tests/conftest.py b/sdk/core/azure-core/tests/conftest.py index eaca5b86a530..fed8afda91d6 100644 --- a/sdk/core/azure-core/tests/conftest.py +++ b/sdk/core/azure-core/tests/conftest.py @@ -71,7 +71,6 @@ def start_testserver(): port = get_port() os.environ["FLASK_APP"] = "coretestserver" os.environ["FLASK_PORT"] = str(port) - # os.environ["FLASK_PORT"] = str(port) cmd = "flask run -p {}".format(port) if os.name == 'nt': #On windows, subprocess creation works without being in the shell child_process = subprocess.Popen(cmd, env=dict(os.environ))