Show More
@@ -216,7 +216,9 b' class CurlSession(object):' | |||||
216 | curl.setopt(curl.WRITEDATA, response_buffer) |
|
216 | curl.setopt(curl.WRITEDATA, response_buffer) | |
217 | curl.perform() |
|
217 | curl.perform() | |
218 |
|
218 | |||
219 | return CurlResponse(response_buffer) |
|
219 | status_code = curl.getinfo(pycurl.HTTP_CODE) | |
|
220 | ||||
|
221 | return CurlResponse(response_buffer, status_code) | |||
220 |
|
222 | |||
221 |
|
223 | |||
222 | class CurlResponse(object): |
|
224 | class CurlResponse(object): | |
@@ -228,13 +230,18 b' class CurlResponse(object):' | |||||
228 | `requests` as a drop in replacement for benchmarking purposes. |
|
230 | `requests` as a drop in replacement for benchmarking purposes. | |
229 | """ |
|
231 | """ | |
230 |
|
232 | |||
231 | def __init__(self, response_buffer): |
|
233 | def __init__(self, response_buffer, status_code): | |
232 | self._response_buffer = response_buffer |
|
234 | self._response_buffer = response_buffer | |
|
235 | self._status_code = status_code | |||
233 |
|
236 | |||
234 | @property |
|
237 | @property | |
235 | def content(self): |
|
238 | def content(self): | |
236 | return self._response_buffer.getvalue() |
|
239 | return self._response_buffer.getvalue() | |
237 |
|
240 | |||
|
241 | @property | |||
|
242 | def status_code(self): | |||
|
243 | return self._status_code | |||
|
244 | ||||
238 |
|
245 | |||
239 | def _create_http_rpc_session(): |
|
246 | def _create_http_rpc_session(): | |
240 | session = CurlSession() |
|
247 | session = CurlSession() |
@@ -196,10 +196,15 b' def _remote_call(url, payload, exception' | |||||
196 | except pycurl.error as e: |
|
196 | except pycurl.error as e: | |
197 | raise exceptions.HttpVCSCommunicationError(e) |
|
197 | raise exceptions.HttpVCSCommunicationError(e) | |
198 |
|
198 | |||
|
199 | if response.status_code >= 400: | |||
|
200 | log.error('Call to %s returned non 200 HTTP code: %s', | |||
|
201 | url, response.status_code) | |||
|
202 | raise exceptions.HttpVCSCommunicationError(repr(response.content)) | |||
|
203 | ||||
199 | try: |
|
204 | try: | |
200 | response = msgpack.unpackb(response.content) |
|
205 | response = msgpack.unpackb(response.content) | |
201 | except Exception: |
|
206 | except Exception: | |
202 |
log.exception('Failed to decode re |
|
207 | log.exception('Failed to decode response %r', response.content) | |
203 | raise |
|
208 | raise | |
204 |
|
209 | |||
205 | error = response.get('error') |
|
210 | error = response.get('error') |
@@ -25,20 +25,7 b' import msgpack' | |||||
25 | import pytest |
|
25 | import pytest | |
26 |
|
26 | |||
27 | from rhodecode.lib import vcs |
|
27 | from rhodecode.lib import vcs | |
28 | from rhodecode.lib.vcs import client_http |
|
28 | from rhodecode.lib.vcs import client_http, exceptions | |
29 |
|
||||
30 |
|
||||
31 | def test_uses_persistent_http_connections(caplog, vcsbackend_hg): |
|
|||
32 | repo = vcsbackend_hg.repo |
|
|||
33 | remote_call = repo._remote.branches |
|
|||
34 |
|
||||
35 | with caplog.at_level(logging.INFO): |
|
|||
36 | for x in range(5): |
|
|||
37 | remote_call(normal=True, closed=False) |
|
|||
38 |
|
||||
39 | new_connections = [ |
|
|||
40 | r for r in caplog.record_tuples if is_new_connection(*r)] |
|
|||
41 | assert len(new_connections) <= 1 |
|
|||
42 |
|
29 | |||
43 |
|
30 | |||
44 | def is_new_connection(logger, level, message): |
|
31 | def is_new_connection(logger, level, message): | |
@@ -53,7 +40,24 b' def stub_session():' | |||||
53 | Stub of `requests.Session()`. |
|
40 | Stub of `requests.Session()`. | |
54 | """ |
|
41 | """ | |
55 | session = mock.Mock() |
|
42 | session = mock.Mock() | |
56 | session.post().content = msgpack.packb({}) |
|
43 | post = session.post() | |
|
44 | post.content = msgpack.packb({}) | |||
|
45 | post.status_code = 200 | |||
|
46 | ||||
|
47 | session.reset_mock() | |||
|
48 | return session | |||
|
49 | ||||
|
50 | ||||
|
51 | @pytest.fixture | |||
|
52 | def stub_fail_session(): | |||
|
53 | """ | |||
|
54 | Stub of `requests.Session()`. | |||
|
55 | """ | |||
|
56 | session = mock.Mock() | |||
|
57 | post = session.post() | |||
|
58 | post.content = msgpack.packb({'error': '500'}) | |||
|
59 | post.status_code = 500 | |||
|
60 | ||||
57 | session.reset_mock() |
|
61 | session.reset_mock() | |
58 | return session |
|
62 | return session | |
59 |
|
63 | |||
@@ -68,6 +72,29 b' def stub_session_factory(stub_session):' | |||||
68 | return session_factory |
|
72 | return session_factory | |
69 |
|
73 | |||
70 |
|
74 | |||
|
75 | @pytest.fixture | |||
|
76 | def stub_session_failing_factory(stub_fail_session): | |||
|
77 | """ | |||
|
78 | Stub of `rhodecode.lib.vcs.client_http.ThreadlocalSessionFactory`. | |||
|
79 | """ | |||
|
80 | session_factory = mock.Mock() | |||
|
81 | session_factory.return_value = stub_fail_session | |||
|
82 | return session_factory | |||
|
83 | ||||
|
84 | ||||
|
85 | def test_uses_persistent_http_connections(caplog, vcsbackend_hg): | |||
|
86 | repo = vcsbackend_hg.repo | |||
|
87 | remote_call = repo._remote.branches | |||
|
88 | ||||
|
89 | with caplog.at_level(logging.INFO): | |||
|
90 | for x in range(5): | |||
|
91 | remote_call(normal=True, closed=False) | |||
|
92 | ||||
|
93 | new_connections = [ | |||
|
94 | r for r in caplog.record_tuples if is_new_connection(*r)] | |||
|
95 | assert len(new_connections) <= 1 | |||
|
96 | ||||
|
97 | ||||
71 | def test_repo_maker_uses_session_for_classmethods(stub_session_factory): |
|
98 | def test_repo_maker_uses_session_for_classmethods(stub_session_factory): | |
72 | repo_maker = client_http.RepoMaker( |
|
99 | repo_maker = client_http.RepoMaker( | |
73 | 'server_and_port', 'endpoint', 'test_dummy_scm', stub_session_factory) |
|
100 | 'server_and_port', 'endpoint', 'test_dummy_scm', stub_session_factory) | |
@@ -94,3 +121,13 b' def test_connect_passes_in_the_same_sess' | |||||
94 | session_factory.return_value = stub_session |
|
121 | session_factory.return_value = stub_session | |
95 |
|
122 | |||
96 | vcs.connect_http('server_and_port') |
|
123 | vcs.connect_http('server_and_port') | |
|
124 | ||||
|
125 | ||||
|
126 | def test_repo_maker_uses_session_that_throws_error( | |||
|
127 | stub_session_failing_factory, config): | |||
|
128 | repo_maker = client_http.RepoMaker( | |||
|
129 | 'server_and_port', 'endpoint', 'test_dummy_scm', stub_session_failing_factory) | |||
|
130 | repo = repo_maker('stub_path', config) | |||
|
131 | ||||
|
132 | with pytest.raises(exceptions.HttpVCSCommunicationError): | |||
|
133 | repo.example_call() |
General Comments 0
You need to be logged in to leave comments.
Login now