| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| # pylint: disable=missing-docstring,protected-access,too-many-locals,too-many-arguments |
| |
| from __future__ import absolute_import |
| |
| from collections import namedtuple |
| |
| import mock |
| import pytest |
| import requests.exceptions |
| import ujson |
| |
| from mesos import http |
| |
| |
| def test_resource(): |
| # test initialization |
| resource = http.Resource('http://some.domain/some/prefix') |
| assert resource.url.geturl() == 'http://some.domain/some/prefix' |
| |
| # test subresource |
| subresource = resource.subresource('some/subpath') |
| assert subresource.url.geturl() == \ |
| 'http://some.domain/some/prefix/some/subpath' |
| |
| |
| @pytest.mark.parametrize( |
| ['default_tos', |
| 'override_tos', |
| 'expected_request_calls'], |
| [(None, |
| None, |
| [mock.call(auth=None, |
| headers={'Content-Type': 'applicatioin/json', |
| 'some-header-key': 'some-header-val'}, |
| method='GET', |
| params=None, |
| somekey='someval', |
| timeout=None, |
| url='http://some.domain/some/prefix')]), |
| (10, |
| None, |
| [mock.call(auth=None, |
| headers={'Content-Type': 'applicatioin/json', |
| 'some-header-key': 'some-header-val'}, |
| method='GET', |
| params=None, |
| somekey='someval', |
| timeout=10, |
| url='http://some.domain/some/prefix')]), |
| (10, |
| 100, |
| [mock.call(auth=None, |
| headers={'Content-Type': 'applicatioin/json', |
| 'some-header-key': 'some-header-val'}, |
| method='GET', |
| params=None, |
| somekey='someval', |
| timeout=100, |
| url='http://some.domain/some/prefix')])]) |
| def test_resource_request(mock_mesos_http_request, default_tos, override_tos, |
| expected_request_calls): |
| # test request |
| mock_response = mock.Mock(status_code=200) |
| mock_mesos_http_request.return_value = mock_response |
| resource = http.Resource('http://some.domain/some/prefix', |
| default_timeout=default_tos, |
| default_headers={ |
| 'Content-Type': 'applicatioin/json'}) |
| ret = resource.request(http.METHOD_GET, |
| additional_headers={ |
| 'some-header-key': 'some-header-val' |
| }, |
| timeout=override_tos, |
| auth=None, |
| use_gzip_encoding=False, |
| max_attempts=1, |
| params=None, |
| somekey='someval') |
| assert ret == mock_response |
| assert mock_mesos_http_request.mock_calls == expected_request_calls |
| |
| |
| SomeModel = namedtuple('SomeModel', ['some']) |
| |
| RequestJsonParams = namedtuple('RequestJsonParams', |
| [ |
| 'default_tos', |
| 'override_tos', |
| 'json_payload', |
| 'obj_decoder', |
| 'request_exception', |
| 'resp_status', |
| 'json_exception', |
| 'expected_exception', |
| 'expected_additional_kwargs', |
| ]) |
| |
| |
| @mock.patch('mesos.http.ujson.loads') |
| @pytest.mark.parametrize( |
| RequestJsonParams._fields, |
| [ |
| RequestJsonParams( |
| default_tos=None, |
| override_tos=None, |
| json_payload={'some': 'payload'}, |
| obj_decoder=None, |
| request_exception=None, |
| resp_status=200, |
| json_exception=None, |
| expected_exception=None, |
| expected_additional_kwargs=[{}]), |
| RequestJsonParams( |
| default_tos=None, |
| override_tos=None, |
| json_payload={'some': 'payload'}, |
| obj_decoder=lambda d: SomeModel(**d), |
| request_exception=None, |
| resp_status=200, |
| json_exception=None, |
| expected_exception=None, |
| expected_additional_kwargs=[{}]), |
| RequestJsonParams( |
| default_tos=None, |
| override_tos=None, |
| json_payload={'some': 'payload'}, |
| obj_decoder=None, |
| request_exception=requests.exceptions.SSLError, |
| resp_status=200, |
| json_exception=None, |
| expected_exception=http.MesosException, |
| expected_additional_kwargs=[{}]), |
| RequestJsonParams( |
| default_tos=None, |
| override_tos=None, |
| json_payload={'some': 'payload'}, |
| obj_decoder=None, |
| request_exception=requests.exceptions.ConnectionError, |
| resp_status=200, |
| json_exception=None, |
| expected_exception=http.MesosException, |
| expected_additional_kwargs=[{}]), |
| RequestJsonParams( |
| default_tos=None, |
| override_tos=None, |
| json_payload={'some': 'payload'}, |
| obj_decoder=None, |
| request_exception=requests.exceptions.Timeout, |
| resp_status=200, |
| json_exception=None, |
| expected_exception=http.MesosException, |
| expected_additional_kwargs=[{}]), |
| RequestJsonParams( |
| default_tos=None, |
| override_tos=None, |
| json_payload={'some': 'payload'}, |
| obj_decoder=None, |
| request_exception=requests.exceptions.RequestException, |
| resp_status=200, |
| json_exception=None, |
| expected_exception=http.MesosException, |
| expected_additional_kwargs=[{}]), |
| RequestJsonParams( |
| default_tos=None, |
| override_tos=None, |
| json_payload={'some': 'payload'}, |
| obj_decoder=None, |
| request_exception=None, |
| resp_status=299, |
| json_exception=None, |
| expected_exception=None, |
| expected_additional_kwargs=[{}]), |
| RequestJsonParams( |
| default_tos=None, |
| override_tos=None, |
| json_payload={'some': 'payload'}, |
| obj_decoder=None, |
| request_exception=None, |
| resp_status=200, |
| json_exception=ValueError, |
| expected_exception=http.MesosException, |
| expected_additional_kwargs=[{}]), |
| RequestJsonParams( |
| default_tos=10, |
| override_tos=None, |
| json_payload={'some': 'payload'}, |
| obj_decoder=None, |
| request_exception=None, |
| resp_status=200, |
| json_exception=None, |
| expected_exception=None, |
| expected_additional_kwargs=[dict(timeout=10)]), |
| RequestJsonParams( |
| default_tos=10, |
| override_tos=100, |
| json_payload={'some': 'payload'}, |
| obj_decoder=None, |
| request_exception=None, |
| resp_status=200, |
| json_exception=None, |
| expected_exception=None, |
| expected_additional_kwargs=[dict(timeout=100)]), |
| RequestJsonParams( |
| default_tos=None, |
| override_tos=None, |
| json_payload={'some': 'payload'}, |
| obj_decoder=None, |
| request_exception=None, |
| resp_status=400, |
| json_exception=None, |
| expected_exception=http.Resource.ERROR_CODE_MAP[400], |
| expected_additional_kwargs=[{}]), |
| RequestJsonParams( |
| default_tos=None, |
| override_tos=None, |
| json_payload={'some': 'payload'}, |
| obj_decoder=None, |
| request_exception=None, |
| resp_status=999, |
| json_exception=None, |
| expected_exception=http.MesosException, |
| expected_additional_kwargs=[{}])]) |
| def test_resource_request_json( |
| mock_ujson_loads, |
| mock_mesos_http_request, |
| default_tos, |
| override_tos, |
| json_payload, |
| obj_decoder, |
| request_exception, |
| resp_status, |
| json_exception, |
| expected_exception, |
| expected_additional_kwargs): |
| call_kwargs = dict(method=http.METHOD_POST, |
| json={'some': 'payload'}, |
| timeout=None, |
| url='http://some.domain/some/prefix', |
| auth=None, |
| headers={'Accept': 'application/json', |
| 'Accept-Encoding': 'gzip'}, |
| params=None) |
| mock_calls = [] |
| for kwargs in expected_additional_kwargs: |
| call_kwargs.update(kwargs) |
| mock_calls.append(mock.call(**call_kwargs)) |
| |
| def json_side_effect(_): |
| if json_exception is None: |
| return {'some': 'return_value'} |
| else: |
| raise json_exception |
| |
| def request_side_effect(*_, **__): |
| if request_exception is None: |
| return mock.Mock(status_code=resp_status) |
| else: |
| raise request_exception |
| |
| mock_mesos_http_request.side_effect = request_side_effect |
| mock_ujson_loads.side_effect = json_side_effect |
| |
| resource = http.Resource('http://some.domain/some/prefix', |
| default_timeout=default_tos, |
| default_auth=None, |
| default_max_attempts=1, |
| default_use_gzip_encoding=True) |
| |
| if expected_exception is None: |
| ret = resource.request_json(http.METHOD_POST, |
| timeout=override_tos, |
| payload=json_payload, |
| decoder=obj_decoder) |
| expected_ret = {'some': 'return_value'} |
| if obj_decoder is None: |
| assert ret == expected_ret |
| else: |
| assert ret == SomeModel(**expected_ret) |
| else: |
| with pytest.raises(expected_exception): |
| resource.request_json(http.METHOD_POST, |
| timeout=override_tos, |
| payload=json_payload) |
| |
| assert mock_mesos_http_request.mock_calls == mock_calls |
| |
| |
| def test_resource_get_json(mock_mesos_http_request): |
| mock_mesos_http_request.return_value = mock.Mock( |
| status_code=200, |
| text=ujson.dumps({'hello': 'world'}), |
| ) |
| mock_auth = mock.Mock() |
| resource = http.Resource('http://some.domain/some/prefix', |
| default_timeout=100, |
| default_auth=mock_auth, |
| default_max_attempts=1, |
| default_use_gzip_encoding=True) |
| ret = resource.get_json() |
| assert mock_mesos_http_request.mock_calls == [ |
| mock.call( |
| json=None, |
| method='GET', |
| url='http://some.domain/some/prefix', |
| auth=mock_auth, |
| headers={'Accept-Encoding': 'gzip', |
| 'Accept': 'application/json'}, |
| params=None, |
| timeout=100, |
| ) |
| ] |
| assert ret == {'hello': 'world'} |
| |
| |
| def test_resource_post_json(mock_mesos_http_request): |
| mock_mesos_http_request.return_value = mock.Mock( |
| status_code=200, |
| text=ujson.dumps({'hello': 'world'}), |
| ) |
| mock_auth = mock.Mock() |
| resource = http.Resource('http://some.domain/some/prefix', |
| default_timeout=100, |
| default_auth=mock_auth, |
| default_max_attempts=1, |
| default_use_gzip_encoding=True) |
| ret = resource.post_json(payload={'somekey': 'someval'}) |
| assert mock_mesos_http_request.mock_calls == [ |
| mock.call(json={'somekey': 'someval'}, |
| method='POST', |
| url='http://some.domain/some/prefix', |
| auth=mock_auth, |
| headers={'Accept-Encoding': 'gzip', |
| 'Accept': 'application/json'}, |
| params=None, |
| timeout=100) |
| ] |
| assert ret == {'hello': 'world'} |