예제 #1
0
# 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 pytest
from azure.core.exceptions import (
    ResourceNotFoundError,
    ResourceExistsError,
    map_error,
    ErrorMap,
)
from utils import request_and_responses_product, create_http_response, HTTP_RESPONSES

@pytest.mark.parametrize("http_request,http_response", request_and_responses_product(HTTP_RESPONSES))
def test_error_map(http_request, http_response):
    request = http_request("GET", "")
    response = create_http_response(http_response, request, None)
    error_map = {
        404: ResourceNotFoundError
    }
    with pytest.raises(ResourceNotFoundError):
        map_error(404, response, error_map)

@pytest.mark.parametrize("http_request,http_response", request_and_responses_product(HTTP_RESPONSES))
def test_error_map_no_default(http_request, http_response):
    request = http_request("GET", "")
    response = create_http_response(http_response, request, None)
    error_map = ErrorMap({
        404: ResourceNotFoundError
    assert serialized == expected


@pytest.mark.parametrize("http_request", HTTP_REQUESTS)
def test_url_join(http_request):
    assert _urljoin('devstoreaccount1', '') == 'devstoreaccount1/'
    assert _urljoin('devstoreaccount1',
                    'testdir/') == 'devstoreaccount1/testdir/'
    assert _urljoin('devstoreaccount1/', '') == 'devstoreaccount1/'
    assert _urljoin('devstoreaccount1/',
                    'testdir/') == 'devstoreaccount1/testdir/'


@pytest.mark.parametrize(
    "http_request,http_response",
    request_and_responses_product(HTTP_CLIENT_TRANSPORT_RESPONSES))
def test_http_client_response(port, http_request, http_response):
    # Create a core request
    request = http_request("GET", "http://localhost:{}".format(port))

    # Fake a transport based on http.client
    conn = HTTPConnection("localhost", port)
    conn.request("GET", "/get")
    r1 = conn.getresponse()

    response = create_transport_response(http_response, request, r1)
    if is_rest(http_response):
        response.read()

    # Don't assume too much in those assert, since we reach a real server
    assert response.internal_response is r1
예제 #3
0
"""Tests for the HttpLoggingPolicy."""

import logging
import types
import pytest
import sys
from unittest.mock import Mock
from azure.core.pipeline import (PipelineResponse, PipelineRequest,
                                 PipelineContext)
from azure.core.pipeline.policies import (
    HttpLoggingPolicy, )
from utils import HTTP_RESPONSES, request_and_responses_product, create_http_response


@pytest.mark.parametrize("http_request,http_response",
                         request_and_responses_product(HTTP_RESPONSES))
def test_http_logger(http_request, http_response):
    class MockHandler(logging.Handler):
        def __init__(self):
            super(MockHandler, self).__init__()
            self.messages = []

        def reset(self):
            self.messages = []

        def emit(self, record):
            self.messages.append(record)

    mock_handler = MockHandler()

    logger = logging.getLogger("testlogger")
예제 #4
0
import requests
from azure.core.pipeline.transport import (
    AsyncHttpTransport,
    AsyncioRequestsTransportResponse,
    AioHttpTransport,
)
from azure.core.pipeline import AsyncPipeline, PipelineResponse
from azure.core.pipeline.transport._aiohttp import AioHttpStreamDownloadGenerator
from unittest import mock
import pytest
from utils import request_and_responses_product, ASYNC_HTTP_RESPONSES, create_http_response


@pytest.mark.asyncio
@pytest.mark.parametrize("http_request,http_response",
                         request_and_responses_product(ASYNC_HTTP_RESPONSES))
async def test_connection_error_response(http_request, http_response):
    class MockSession(object):
        def __init__(self):
            self.auto_decompress = True

        @property
        def auto_decompress(self):
            return self.auto_decompress

    class MockTransport(AsyncHttpTransport):
        def __init__(self):
            self._count = 0
            self.session = MockSession

        async def __aexit__(self, exc_type, exc_val, exc_tb):
class TestBasePolling(object):

    convert = re.compile('([a-z0-9])([A-Z])')

    @staticmethod
    def mock_send(http_request,
                  http_response,
                  method,
                  status,
                  headers=None,
                  body=RESPONSE_BODY):
        if headers is None:
            headers = {}
        response = Response()
        response._content_consumed = True
        response._content = json.dumps(body).encode(
            'ascii') if body is not None else None
        response.request = Request()
        response.request.method = method
        response.request.url = RESOURCE_URL
        response.request.headers = {
            'x-ms-client-request-id': '67f4dd4e-6262-45e1-8bed-5c45cf23b6d9'
        }
        response.status_code = status
        response.headers = headers
        response.headers.update(
            {"content-type": "application/json; charset=utf8"})
        response.reason = "OK"

        if is_rest(http_request):
            request = http_request(
                response.request.method,
                response.request.url,
                headers=response.request.headers,
                content=body,
            )
        else:
            request = CLIENT._request(
                response.request.method,
                response.request.url,
                None,  # params
                response.request.headers,
                body,
                None,  # form_content
                None  # stream_content
            )
        response = create_transport_response(
            http_response,
            request,
            response,
        )
        return PipelineResponse(
            request,
            response,
            None  # context
        )

    @staticmethod
    def mock_update(http_request, http_response, url, headers=None):
        response = Response()
        response._content_consumed = True
        response.request = mock.create_autospec(Request)
        response.request.method = 'GET'
        response.headers = headers or {}
        response.headers.update(
            {"content-type": "application/json; charset=utf8"})
        response.reason = "OK"

        if url == ASYNC_URL:
            response.request.url = url
            response.status_code = POLLING_STATUS
            response._content = ASYNC_BODY.encode('ascii')
            response.randomFieldFromPollAsyncOpHeader = None

        elif url == LOCATION_URL:
            response.request.url = url
            response.status_code = POLLING_STATUS
            response._content = LOCATION_BODY.encode('ascii')
            response.randomFieldFromPollLocationHeader = None

        elif url == ERROR:
            raise BadEndpointError("boom")

        elif url == RESOURCE_URL:
            response.request.url = url
            response.status_code = POLLING_STATUS
            response._content = RESOURCE_BODY.encode('ascii')

        else:
            raise Exception('URL does not match')
        request = http_request(
            response.request.method,
            response.request.url,
        )
        response = create_transport_response(
            http_response,
            request,
            response,
        )
        return PipelineResponse(
            request,
            response,
            None  # context
        )

    @staticmethod
    def mock_outputs(pipeline_response):
        response = pipeline_response.http_response
        try:
            body = json.loads(response.text())
        except ValueError:
            raise DecodeError("Impossible to deserialize")

        body = {
            TestBasePolling.convert.sub(r'\1_\2', k).lower(): v
            for k, v in body.items()
        }
        properties = body.setdefault('properties', {})
        if 'name' in body:
            properties['name'] = body['name']
        if properties:
            properties = {
                TestBasePolling.convert.sub(r'\1_\2', k).lower(): v
                for k, v in properties.items()
            }
            del body['properties']
            body.update(properties)
            resource = SimpleResource(**body)
        else:
            raise DecodeError("Impossible to deserialize")
            resource = SimpleResource(**body)
        return resource

    @staticmethod
    def mock_deserialization_no_body(pipeline_response):
        """Use this mock when you don't expect a return (last body irrelevant)
        """
        return None

    @pytest.mark.parametrize(
        "http_request,http_response",
        request_and_responses_product(REQUESTS_TRANSPORT_RESPONSES))
    def test_long_running_put(self, http_request, http_response):
        #TODO: Test custom header field

        # Test throw on non LRO related status code
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'PUT', 1000, {})
        CLIENT.http_request_type = http_request
        CLIENT.http_response_type = http_response
        with pytest.raises(HttpResponseError):
            LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                      LROBasePolling(0)).result()

        # Test with no polling necessary
        response_body = {
            'properties': {
                'provisioningState': 'Succeeded'
            },
            'name': TEST_NAME
        }
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'PUT', 201, {}, response_body)

        def no_update_allowed(url, headers=None):
            raise ValueError("Should not try to update")

        poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                         LROBasePolling(0))
        assert poll.result().name == TEST_NAME
        assert not hasattr(poll._polling_method._pipeline_response,
                           'randomFieldFromPollAsyncOpHeader')

        # Test polling from operation-location header
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'PUT', 201,
                                             {'operation-location': ASYNC_URL})
        poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                         LROBasePolling(0))
        assert poll.result().name == TEST_NAME
        assert not hasattr(poll._polling_method._pipeline_response,
                           'randomFieldFromPollAsyncOpHeader')

        # Test polling location header
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'PUT', 201,
                                             {'location': LOCATION_URL})
        poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                         LROBasePolling(0))
        assert poll.result().name == TEST_NAME
        assert poll._polling_method._pipeline_response.http_response.internal_response.randomFieldFromPollLocationHeader is None

        # Test polling initial payload invalid (SQLDb)
        response_body = {}  # Empty will raise
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'PUT', 201,
                                             {'location': LOCATION_URL},
                                             response_body)
        poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                         LROBasePolling(0))
        assert poll.result().name == TEST_NAME
        assert poll._polling_method._pipeline_response.http_response.internal_response.randomFieldFromPollLocationHeader is None

        # Test fail to poll from operation-location header
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'PUT', 201,
                                             {'operation-location': ERROR})
        with pytest.raises(BadEndpointError):
            poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                             LROBasePolling(0)).result()

        # Test fail to poll from location header
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'PUT', 201, {'location': ERROR})
        with pytest.raises(BadEndpointError):
            poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                             LROBasePolling(0)).result()

    @pytest.mark.parametrize(
        "http_request,http_response",
        request_and_responses_product(REQUESTS_TRANSPORT_RESPONSES))
    def test_long_running_patch(self, http_request, http_response):
        CLIENT.http_request_type = http_request
        CLIENT.http_response_type = http_response
        # Test polling from location header
        response = TestBasePolling.mock_send(
            http_request,
            http_response,
            'PATCH',
            202, {'location': LOCATION_URL},
            body={'properties': {
                'provisioningState': 'Succeeded'
            }})
        poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                         LROBasePolling(0))
        assert poll.result().name == TEST_NAME
        assert poll._polling_method._pipeline_response.http_response.internal_response.randomFieldFromPollLocationHeader is None

        # Test polling from operation-location header
        response = TestBasePolling.mock_send(
            http_request,
            http_response,
            'PATCH',
            202, {'operation-location': ASYNC_URL},
            body={'properties': {
                'provisioningState': 'Succeeded'
            }})
        poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                         LROBasePolling(0))
        assert poll.result().name == TEST_NAME
        assert not hasattr(poll._polling_method._pipeline_response,
                           'randomFieldFromPollAsyncOpHeader')

        # Test polling from location header
        response = TestBasePolling.mock_send(
            http_request,
            http_response,
            'PATCH',
            200, {'location': LOCATION_URL},
            body={'properties': {
                'provisioningState': 'Succeeded'
            }})
        poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                         LROBasePolling(0))
        assert poll.result().name == TEST_NAME
        assert poll._polling_method._pipeline_response.http_response.internal_response.randomFieldFromPollLocationHeader is None

        # Test polling from operation-location header
        response = TestBasePolling.mock_send(
            http_request,
            http_response,
            'PATCH',
            200, {'operation-location': ASYNC_URL},
            body={'properties': {
                'provisioningState': 'Succeeded'
            }})
        poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                         LROBasePolling(0))
        assert poll.result().name == TEST_NAME
        assert not hasattr(poll._polling_method._pipeline_response,
                           'randomFieldFromPollAsyncOpHeader')

        # Test fail to poll from operation-location header
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'PATCH', 202,
                                             {'operation-location': ERROR})
        with pytest.raises(BadEndpointError):
            poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                             LROBasePolling(0)).result()

        # Test fail to poll from location header
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'PATCH', 202, {'location': ERROR})
        with pytest.raises(BadEndpointError):
            poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                             LROBasePolling(0)).result()

    @pytest.mark.parametrize(
        "http_request,http_response",
        request_and_responses_product(REQUESTS_TRANSPORT_RESPONSES))
    def test_long_running_delete(self, http_request, http_response):
        # Test polling from operation-location header
        response = TestBasePolling.mock_send(http_request,
                                             http_response,
                                             'DELETE',
                                             202,
                                             {'operation-location': ASYNC_URL},
                                             body="")
        CLIENT.http_request_type = http_request
        CLIENT.http_response_type = http_response
        poll = LROPoller(CLIENT, response,
                         TestBasePolling.mock_deserialization_no_body,
                         LROBasePolling(0))
        poll.wait()
        assert poll._polling_method._pipeline_response.http_response.internal_response.randomFieldFromPollAsyncOpHeader is None

    @pytest.mark.parametrize(
        "http_request,http_response",
        request_and_responses_product(REQUESTS_TRANSPORT_RESPONSES))
    def test_long_running_post_legacy(self, http_request, http_response):
        # Former oooooold tests to refactor one day to something more readble

        # Test polling from operation-location header
        response = TestBasePolling.mock_send(
            http_request,
            http_response,
            'POST',
            201, {'operation-location': ASYNC_URL},
            body={'properties': {
                'provisioningState': 'Succeeded'
            }})
        CLIENT.http_request_type = http_request
        CLIENT.http_response_type = http_response
        poll = LROPoller(CLIENT, response,
                         TestBasePolling.mock_deserialization_no_body,
                         LROBasePolling(0))
        poll.wait()
        assert poll._polling_method._pipeline_response.http_response.internal_response.randomFieldFromPollAsyncOpHeader is None

        # Test polling from operation-location header
        response = TestBasePolling.mock_send(
            http_request,
            http_response,
            'POST',
            202, {'operation-location': ASYNC_URL},
            body={'properties': {
                'provisioningState': 'Succeeded'
            }})
        poll = LROPoller(CLIENT, response,
                         TestBasePolling.mock_deserialization_no_body,
                         LROBasePolling(0))
        poll.wait()
        assert poll._polling_method._pipeline_response.http_response.internal_response.randomFieldFromPollAsyncOpHeader is None

        # Test polling from location header
        response = TestBasePolling.mock_send(
            http_request,
            http_response,
            'POST',
            202, {'location': LOCATION_URL},
            body={'properties': {
                'provisioningState': 'Succeeded'
            }})
        poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                         LROBasePolling(0))
        assert poll.result().name == TEST_NAME
        assert poll._polling_method._pipeline_response.http_response.internal_response.randomFieldFromPollLocationHeader is None

        # Test fail to poll from operation-location header
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'POST', 202,
                                             {'operation-location': ERROR})
        with pytest.raises(BadEndpointError):
            poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                             LROBasePolling(0)).result()

        # Test fail to poll from location header
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'POST', 202, {'location': ERROR})
        with pytest.raises(BadEndpointError):
            poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                             LROBasePolling(0)).result()

    @pytest.mark.parametrize(
        "http_request,http_response",
        request_and_responses_product(REQUESTS_TRANSPORT_RESPONSES))
    def test_long_running_negative(self, http_request, http_response):
        global LOCATION_BODY
        global POLLING_STATUS
        CLIENT.http_request_type = http_request
        CLIENT.http_response_type = http_response
        # Test LRO PUT throws for invalid json
        LOCATION_BODY = '{'
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'POST', 202,
                                             {'location': LOCATION_URL})
        poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                         LROBasePolling(0))
        with pytest.raises(DecodeError):
            poll.result()

        LOCATION_BODY = '{\'"}'
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'POST', 202,
                                             {'location': LOCATION_URL})
        poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                         LROBasePolling(0))
        with pytest.raises(DecodeError):
            poll.result()

        LOCATION_BODY = '{'
        POLLING_STATUS = 203
        response = TestBasePolling.mock_send(http_request, http_response,
                                             'POST', 202,
                                             {'location': LOCATION_URL})
        poll = LROPoller(CLIENT, response, TestBasePolling.mock_outputs,
                         LROBasePolling(0))
        with pytest.raises(
                HttpResponseError
        ) as error:  # TODO: Node.js raises on deserialization
            poll.result()
        assert error.value.continuation_token == base64.b64encode(
            pickle.dumps(response)).decode('ascii')

        LOCATION_BODY = json.dumps({'name': TEST_NAME})
        POLLING_STATUS = 200
                                          18,
                                          12,
                                          8,
                                          tzinfo=_FixedOffset(-5 * 60))
    with mock.patch('datetime.datetime') as mock_datetime:
        mock_datetime.now.return_value = now_mock_datetime
        mock_datetime.side_effect = lambda *args, **kw: basedatetime(
            *args, **kw)

        assert polling._extract_delay() == 60 * 60  # one hour in seconds
        assert str(mock_datetime.now.call_args[0][0]) == "<FixedOffset -5.0>"


@pytest.mark.parametrize(
    "http_request,http_response",
    request_and_responses_product(REQUESTS_TRANSPORT_RESPONSES))
def test_post(pipeline_client_builder, deserialization_cb, http_request,
              http_response):

    # Test POST LRO with both Location and Operation-Location

    # The initial response contains both Location and Operation-Location, a 202 and no Body
    initial_response = TestBasePolling.mock_send(
        http_request, http_response, 'POST', 202, {
            'location': 'http://example.org/location',
            'operation-location': 'http://example.org/async_monitor',
        }, '')

    def send(request, **kwargs):
        assert request.method == 'GET'
    polling, _ = polling_response

    continuation_token = polling.get_continuation_token()
    assert isinstance(continuation_token, str)

    polling_args = AsyncLROBasePolling.from_continuation_token(
        continuation_token,
        deserialization_callback="deserialization_callback",
        client=client,
    )
    new_polling = AsyncLROBasePolling()
    new_polling.initialize(*polling_args)


@pytest.mark.asyncio
@pytest.mark.parametrize("http_request,http_response", request_and_responses_product(ASYNCIO_REQUESTS_TRANSPORT_RESPONSES))
async def test_post(async_pipeline_client_builder, deserialization_cb, http_request, http_response):

        # Test POST LRO with both Location and Operation-Location

        # The initial response contains both Location and Operation-Location, a 202 and no Body
        initial_response = TestBasePolling.mock_send(
            http_request,
            http_response,
            'POST',
            202,
            {
                'location': 'http://example.org/location',
                'operation-location': 'http://example.org/async_monitor',
            },
            ''
예제 #8
0
        b'--changeset_357de4f7-6d0b-4e02-8cd2-6361411a9525--\r\n'
        b'\r\n'
        b'--batch_357de4f7-6d0b-4e02-8cd2-6361411a9525\r\n'
        b'Content-Type: application/http\r\n'
        b'Content-Transfer-Encoding: binary\r\n'
        b'Content-ID: 2\r\n'
        b'\r\n'
        b'DELETE /container2/blob2 HTTP/1.1\r\n'
        b'\r\n'
        b'\r\n'
        b'--batch_357de4f7-6d0b-4e02-8cd2-6361411a9525--\r\n')


@pytest.mark.asyncio
@pytest.mark.parametrize("http_request,mock_response",
                         request_and_responses_product(MOCK_RESPONSES))
async def test_multipart_receive(http_request, mock_response):
    class ResponsePolicy(object):
        def on_response(self, request, response):
            # type: (PipelineRequest, PipelineResponse) -> None
            response.http_response.headers['x-ms-fun'] = 'true'

    class AsyncResponsePolicy(object):
        async def on_response(self, request, response):
            # type: (PipelineRequest, PipelineResponse) -> None
            response.http_response.headers['x-ms-async-fun'] = 'true'

    req0 = http_request("DELETE", "/container0/blob0")
    req1 = http_request("DELETE", "/container1/blob1")

    request = http_request("POST",