kopia lustrzana https://gitlab.com/jaywink/federation
145 wiersze
6.0 KiB
Python
145 wiersze
6.0 KiB
Python
from unittest.mock import patch, Mock, call
|
|
|
|
import pytest
|
|
from requests import HTTPError
|
|
from requests.exceptions import SSLError, RequestException
|
|
|
|
from federation.utils.network import (
|
|
fetch_document, USER_AGENT, send_document, fetch_host_ip,
|
|
)
|
|
|
|
|
|
class TestFetchDocument:
|
|
call_args = {"timeout": 10, "headers": {'user-agent': USER_AGENT}}
|
|
|
|
@patch("federation.utils.network.requests.get", return_value=Mock(status_code=200, text="foo"))
|
|
def test_extra_headers(self, mock_get):
|
|
fetch_document("https://example.com/foo", extra_headers={'accept': 'application/activity+json'})
|
|
mock_get.assert_called_once_with('https://example.com/foo', timeout=10, headers={
|
|
'user-agent': USER_AGENT, 'accept': 'application/activity+json',
|
|
})
|
|
|
|
def test_raises_without_url_and_host(self):
|
|
with pytest.raises(ValueError):
|
|
fetch_document()
|
|
|
|
@patch("federation.utils.network.requests.get")
|
|
def test_url_is_called(self, mock_get):
|
|
mock_get.return_value = Mock(status_code=200, text="foo")
|
|
fetch_document("https://localhost")
|
|
assert mock_get.called
|
|
|
|
@patch("federation.utils.network.requests.get")
|
|
def test_host_is_called_with_https_first_then_http(self, mock_get):
|
|
def mock_failing_https_get(url, *args, **kwargs):
|
|
if url.find("https://") > -1:
|
|
raise HTTPError()
|
|
return Mock(status_code=200, text="foo")
|
|
mock_get.side_effect = mock_failing_https_get
|
|
fetch_document(host="localhost")
|
|
assert mock_get.call_count == 2
|
|
assert mock_get.call_args_list == [
|
|
call("https://localhost/", **self.call_args),
|
|
call("http://localhost/", **self.call_args),
|
|
]
|
|
|
|
@patch("federation.utils.network.requests.get")
|
|
def test_host_is_sanitized(self, mock_get):
|
|
mock_get.return_value = Mock(status_code=200, text="foo")
|
|
fetch_document(host="http://localhost")
|
|
assert mock_get.call_args_list == [
|
|
call("https://localhost/", **self.call_args)
|
|
]
|
|
|
|
@patch("federation.utils.network.requests.get")
|
|
def test_path_is_sanitized(self, mock_get):
|
|
mock_get.return_value = Mock(status_code=200, text="foo")
|
|
fetch_document(host="localhost", path="foobar/bazfoo")
|
|
assert mock_get.call_args_list == [
|
|
call("https://localhost/foobar/bazfoo", **self.call_args)
|
|
]
|
|
|
|
@patch("federation.utils.network.requests.get")
|
|
def test_exception_is_raised_if_both_protocols_fail(self, mock_get):
|
|
mock_get.side_effect = HTTPError
|
|
doc, code, exc = fetch_document(host="localhost")
|
|
assert mock_get.call_count == 2
|
|
assert doc == None
|
|
assert code == None
|
|
assert exc.__class__ == HTTPError
|
|
|
|
@patch("federation.utils.network.requests.get")
|
|
def test_exception_is_raised_if_url_fails(self, mock_get):
|
|
mock_get.side_effect = HTTPError
|
|
doc, code, exc = fetch_document("localhost")
|
|
assert mock_get.call_count == 1
|
|
assert doc == None
|
|
assert code == None
|
|
assert exc.__class__ == HTTPError
|
|
|
|
@patch("federation.utils.network.requests.get")
|
|
def test_exception_is_raised_if_http_fails_and_raise_ssl_errors_true(self, mock_get):
|
|
mock_get.side_effect = SSLError
|
|
doc, code, exc = fetch_document("localhost")
|
|
assert mock_get.call_count == 1
|
|
assert doc == None
|
|
assert code == None
|
|
assert exc.__class__ == SSLError
|
|
|
|
@patch("federation.utils.network.requests.get")
|
|
def test_exception_is_raised_on_network_error(self, mock_get):
|
|
mock_get.side_effect = RequestException
|
|
doc, code, exc = fetch_document(host="localhost")
|
|
assert mock_get.call_count == 1
|
|
assert doc == None
|
|
assert code == None
|
|
assert exc.__class__ == RequestException
|
|
|
|
|
|
class TestFetchHostIp:
|
|
@patch('federation.utils.network.socket.gethostbyname', autospec=True, return_value='127.0.0.1')
|
|
def test_calls(self, mock_get_ip):
|
|
result = fetch_host_ip('domain.local')
|
|
assert result == '127.0.0.1'
|
|
mock_get_ip.assert_called_once_with('domain.local')
|
|
|
|
|
|
class TestSendDocument:
|
|
call_args = {"timeout": 10, "headers": {'user-agent': USER_AGENT}}
|
|
|
|
@patch("federation.utils.network.requests.post", return_value=Mock(status_code=200))
|
|
def test_post_is_called(self, mock_post):
|
|
code, exc = send_document("http://localhost", {"foo": "bar"})
|
|
mock_post.assert_called_once_with(
|
|
"http://localhost", data={"foo": "bar"}, **self.call_args
|
|
)
|
|
assert code == 200
|
|
assert exc == None
|
|
|
|
@patch("federation.utils.network.requests.post", side_effect=RequestException)
|
|
def test_post_raises_and_returns_exception(self, mock_post):
|
|
code, exc = send_document("http://localhost", {"foo": "bar"})
|
|
assert code == None
|
|
assert exc.__class__ == RequestException
|
|
|
|
@patch("federation.utils.network.requests.post", return_value=Mock(status_code=200))
|
|
def test_post_called_with_only_one_headers_kwarg(self, mock_post):
|
|
# A failure might raise:
|
|
# TypeError: MagicMock object got multiple values for keyword argument 'headers'
|
|
send_document("http://localhost", {"foo": "bar"}, **self.call_args)
|
|
mock_post.assert_called_once_with(
|
|
"http://localhost", data={"foo": "bar"}, **self.call_args
|
|
)
|
|
|
|
@patch("federation.utils.network.requests.post", return_value=Mock(status_code=200))
|
|
def test_headers_in_either_case_are_handled_without_exception(self, mock_post):
|
|
send_document("http://localhost", {"foo": "bar"}, **self.call_args)
|
|
mock_post.assert_called_once_with(
|
|
"http://localhost", data={"foo": "bar"}, headers={'user-agent': USER_AGENT}, timeout=10
|
|
)
|
|
mock_post.reset_mock()
|
|
send_document("http://localhost", {"foo": "bar"}, headers={'User-Agent': USER_AGENT})
|
|
mock_post.assert_called_once_with(
|
|
"http://localhost", data={"foo": "bar"}, headers={'User-Agent': USER_AGENT}, timeout=10
|
|
)
|