##// END OF EJS Templates
fix(tests): fixed callback deamon tests
super-admin -
r5467:912dc7a4 default
parent child Browse files
Show More
@@ -1,360 +1,363 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
19
20 import logging
20 import logging
21 import io
21 import io
22
22
23 import mock
23 import mock
24 import msgpack
24 import msgpack
25 import pytest
25 import pytest
26 import tempfile
26 import tempfile
27
27
28 from rhodecode.lib.hook_daemon import http_hooks_deamon
28 from rhodecode.lib.hook_daemon import http_hooks_deamon
29 from rhodecode.lib.hook_daemon import celery_hooks_deamon
29 from rhodecode.lib.hook_daemon import celery_hooks_deamon
30 from rhodecode.lib.hook_daemon import hook_module
30 from rhodecode.lib.hook_daemon import hook_module
31 from rhodecode.lib.hook_daemon import base as hook_base
31 from rhodecode.lib.hook_daemon import base as hook_base
32 from rhodecode.lib.str_utils import safe_bytes
32 from rhodecode.lib.str_utils import safe_bytes
33 from rhodecode.tests.utils import assert_message_in_log
33 from rhodecode.tests.utils import assert_message_in_log
34 from rhodecode.lib.ext_json import json
34 from rhodecode.lib.ext_json import json
35
35
36 test_proto = http_hooks_deamon.HooksHttpHandler.MSGPACK_HOOKS_PROTO
36 test_proto = http_hooks_deamon.HooksHttpHandler.MSGPACK_HOOKS_PROTO
37
37
38
38
39 class TestHooks(object):
39 class TestHooks(object):
40 def test_hooks_can_be_used_as_a_context_processor(self):
40 def test_hooks_can_be_used_as_a_context_processor(self):
41 hooks = hook_module.Hooks()
41 hooks = hook_module.Hooks()
42 with hooks as return_value:
42 with hooks as return_value:
43 pass
43 pass
44 assert hooks == return_value
44 assert hooks == return_value
45
45
46
46
47 class TestHooksHttpHandler(object):
47 class TestHooksHttpHandler(object):
48 def test_read_request_parses_method_name_and_arguments(self):
48 def test_read_request_parses_method_name_and_arguments(self):
49 data = {
49 data = {
50 'method': 'test',
50 'method': 'test',
51 'extras': {
51 'extras': {
52 'param1': 1,
52 'param1': 1,
53 'param2': 'a'
53 'param2': 'a'
54 }
54 }
55 }
55 }
56 request = self._generate_post_request(data)
56 request = self._generate_post_request(data)
57 hooks_patcher = mock.patch.object(
57 hooks_patcher = mock.patch.object(
58 hook_module.Hooks, data['method'], create=True, return_value=1)
58 hook_module.Hooks, data['method'], create=True, return_value=1)
59
59
60 with hooks_patcher as hooks_mock:
60 with hooks_patcher as hooks_mock:
61 handler = http_hooks_deamon.HooksHttpHandler
61 handler = http_hooks_deamon.HooksHttpHandler
62 handler.DEFAULT_HOOKS_PROTO = test_proto
62 handler.DEFAULT_HOOKS_PROTO = test_proto
63 handler.wbufsize = 10240
63 handler.wbufsize = 10240
64 MockServer(handler, request)
64 MockServer(handler, request)
65
65
66 hooks_mock.assert_called_once_with(data['extras'])
66 hooks_mock.assert_called_once_with(data['extras'])
67
67
68 def test_hooks_serialized_result_is_returned(self):
68 def test_hooks_serialized_result_is_returned(self):
69 request = self._generate_post_request({})
69 request = self._generate_post_request({})
70 rpc_method = 'test'
70 rpc_method = 'test'
71 hook_result = {
71 hook_result = {
72 'first': 'one',
72 'first': 'one',
73 'second': 2
73 'second': 2
74 }
74 }
75 extras = {}
75 extras = {}
76
76
77 # patching our _read to return test method and proto used
77 # patching our _read to return test method and proto used
78 read_patcher = mock.patch.object(
78 read_patcher = mock.patch.object(
79 http_hooks_deamon.HooksHttpHandler, '_read_request',
79 http_hooks_deamon.HooksHttpHandler, '_read_request',
80 return_value=(test_proto, rpc_method, extras))
80 return_value=(test_proto, rpc_method, extras))
81
81
82 # patch Hooks instance to return hook_result data on 'test' call
82 # patch Hooks instance to return hook_result data on 'test' call
83 hooks_patcher = mock.patch.object(
83 hooks_patcher = mock.patch.object(
84 hook_module.Hooks, rpc_method, create=True,
84 hook_module.Hooks, rpc_method, create=True,
85 return_value=hook_result)
85 return_value=hook_result)
86
86
87 with read_patcher, hooks_patcher:
87 with read_patcher, hooks_patcher:
88 handler = http_hooks_deamon.HooksHttpHandler
88 handler = http_hooks_deamon.HooksHttpHandler
89 handler.DEFAULT_HOOKS_PROTO = test_proto
89 handler.DEFAULT_HOOKS_PROTO = test_proto
90 handler.wbufsize = 10240
90 handler.wbufsize = 10240
91 server = MockServer(handler, request)
91 server = MockServer(handler, request)
92
92
93 expected_result = http_hooks_deamon.HooksHttpHandler.serialize_data(hook_result)
93 expected_result = http_hooks_deamon.HooksHttpHandler.serialize_data(hook_result)
94
94
95 server.request.output_stream.seek(0)
95 server.request.output_stream.seek(0)
96 assert server.request.output_stream.readlines()[-1] == expected_result
96 assert server.request.output_stream.readlines()[-1] == expected_result
97
97
98 def test_exception_is_returned_in_response(self):
98 def test_exception_is_returned_in_response(self):
99 request = self._generate_post_request({})
99 request = self._generate_post_request({})
100 rpc_method = 'test'
100 rpc_method = 'test'
101
101
102 read_patcher = mock.patch.object(
102 read_patcher = mock.patch.object(
103 http_hooks_deamon.HooksHttpHandler, '_read_request',
103 http_hooks_deamon.HooksHttpHandler, '_read_request',
104 return_value=(test_proto, rpc_method, {}))
104 return_value=(test_proto, rpc_method, {}))
105
105
106 hooks_patcher = mock.patch.object(
106 hooks_patcher = mock.patch.object(
107 hook_module.Hooks, rpc_method, create=True,
107 hook_module.Hooks, rpc_method, create=True,
108 side_effect=Exception('Test exception'))
108 side_effect=Exception('Test exception'))
109
109
110 with read_patcher, hooks_patcher:
110 with read_patcher, hooks_patcher:
111 handler = http_hooks_deamon.HooksHttpHandler
111 handler = http_hooks_deamon.HooksHttpHandler
112 handler.DEFAULT_HOOKS_PROTO = test_proto
112 handler.DEFAULT_HOOKS_PROTO = test_proto
113 handler.wbufsize = 10240
113 handler.wbufsize = 10240
114 server = MockServer(handler, request)
114 server = MockServer(handler, request)
115
115
116 server.request.output_stream.seek(0)
116 server.request.output_stream.seek(0)
117 data = server.request.output_stream.readlines()
117 data = server.request.output_stream.readlines()
118 msgpack_data = b''.join(data[5:])
118 msgpack_data = b''.join(data[5:])
119 org_exc = http_hooks_deamon.HooksHttpHandler.deserialize_data(msgpack_data)
119 org_exc = http_hooks_deamon.HooksHttpHandler.deserialize_data(msgpack_data)
120 expected_result = {
120 expected_result = {
121 'exception': 'Exception',
121 'exception': 'Exception',
122 'exception_traceback': org_exc['exception_traceback'],
122 'exception_traceback': org_exc['exception_traceback'],
123 'exception_args': ['Test exception']
123 'exception_args': ['Test exception']
124 }
124 }
125 assert org_exc == expected_result
125 assert org_exc == expected_result
126
126
127 def test_log_message_writes_to_debug_log(self, caplog):
127 def test_log_message_writes_to_debug_log(self, caplog):
128 ip_port = ('0.0.0.0', 8888)
128 ip_port = ('0.0.0.0', 8888)
129 handler = http_hooks_deamon.HooksHttpHandler(MockRequest('POST /'), ip_port, mock.Mock())
129 handler = http_hooks_deamon.HooksHttpHandler(MockRequest('POST /'), ip_port, mock.Mock())
130 fake_date = '1/Nov/2015 00:00:00'
130 fake_date = '1/Nov/2015 00:00:00'
131 date_patcher = mock.patch.object(
131 date_patcher = mock.patch.object(
132 handler, 'log_date_time_string', return_value=fake_date)
132 handler, 'log_date_time_string', return_value=fake_date)
133
133
134 with date_patcher, caplog.at_level(logging.DEBUG):
134 with date_patcher, caplog.at_level(logging.DEBUG):
135 handler.log_message('Some message %d, %s', 123, 'string')
135 handler.log_message('Some message %d, %s', 123, 'string')
136
136
137 expected_message = f"HOOKS: client={ip_port} - - [{fake_date}] Some message 123, string"
137 expected_message = f"HOOKS: client={ip_port} - - [{fake_date}] Some message 123, string"
138
138
139 assert_message_in_log(
139 assert_message_in_log(
140 caplog.records, expected_message,
140 caplog.records, expected_message,
141 levelno=logging.DEBUG, module='http_hooks_deamon')
141 levelno=logging.DEBUG, module='http_hooks_deamon')
142
142
143 def _generate_post_request(self, data, proto=test_proto):
143 def _generate_post_request(self, data, proto=test_proto):
144 if proto == http_hooks_deamon.HooksHttpHandler.MSGPACK_HOOKS_PROTO:
144 if proto == http_hooks_deamon.HooksHttpHandler.MSGPACK_HOOKS_PROTO:
145 payload = msgpack.packb(data)
145 payload = msgpack.packb(data)
146 else:
146 else:
147 payload = json.dumps(data)
147 payload = json.dumps(data)
148
148
149 return b'POST / HTTP/1.0\nContent-Length: %d\n\n%b' % (
149 return b'POST / HTTP/1.0\nContent-Length: %d\n\n%b' % (
150 len(payload), payload)
150 len(payload), payload)
151
151
152
152
153 class ThreadedHookCallbackDaemon(object):
153 class ThreadedHookCallbackDaemon(object):
154 def test_constructor_calls_prepare(self):
154 def test_constructor_calls_prepare(self):
155 prepare_daemon_patcher = mock.patch.object(
155 prepare_daemon_patcher = mock.patch.object(
156 http_hooks_deamon.ThreadedHookCallbackDaemon, '_prepare')
156 http_hooks_deamon.ThreadedHookCallbackDaemon, '_prepare')
157 with prepare_daemon_patcher as prepare_daemon_mock:
157 with prepare_daemon_patcher as prepare_daemon_mock:
158 http_hooks_deamon.ThreadedHookCallbackDaemon()
158 http_hooks_deamon.ThreadedHookCallbackDaemon()
159 prepare_daemon_mock.assert_called_once_with()
159 prepare_daemon_mock.assert_called_once_with()
160
160
161 def test_run_is_called_on_context_start(self):
161 def test_run_is_called_on_context_start(self):
162 patchers = mock.patch.multiple(
162 patchers = mock.patch.multiple(
163 http_hooks_deamon.ThreadedHookCallbackDaemon,
163 http_hooks_deamon.ThreadedHookCallbackDaemon,
164 _run=mock.DEFAULT, _prepare=mock.DEFAULT, __exit__=mock.DEFAULT)
164 _run=mock.DEFAULT, _prepare=mock.DEFAULT, __exit__=mock.DEFAULT)
165
165
166 with patchers as mocks:
166 with patchers as mocks:
167 daemon = http_hooks_deamon.ThreadedHookCallbackDaemon()
167 daemon = http_hooks_deamon.ThreadedHookCallbackDaemon()
168 with daemon as daemon_context:
168 with daemon as daemon_context:
169 pass
169 pass
170 mocks['_run'].assert_called_once_with()
170 mocks['_run'].assert_called_once_with()
171 assert daemon_context == daemon
171 assert daemon_context == daemon
172
172
173 def test_stop_is_called_on_context_exit(self):
173 def test_stop_is_called_on_context_exit(self):
174 patchers = mock.patch.multiple(
174 patchers = mock.patch.multiple(
175 http_hooks_deamon.ThreadedHookCallbackDaemon,
175 http_hooks_deamon.ThreadedHookCallbackDaemon,
176 _run=mock.DEFAULT, _prepare=mock.DEFAULT, _stop=mock.DEFAULT)
176 _run=mock.DEFAULT, _prepare=mock.DEFAULT, _stop=mock.DEFAULT)
177
177
178 with patchers as mocks:
178 with patchers as mocks:
179 daemon = http_hooks_deamon.ThreadedHookCallbackDaemon()
179 daemon = http_hooks_deamon.ThreadedHookCallbackDaemon()
180 with daemon as daemon_context:
180 with daemon as daemon_context:
181 assert mocks['_stop'].call_count == 0
181 assert mocks['_stop'].call_count == 0
182
182
183 mocks['_stop'].assert_called_once_with()
183 mocks['_stop'].assert_called_once_with()
184 assert daemon_context == daemon
184 assert daemon_context == daemon
185
185
186
186
187 class TestHttpHooksCallbackDaemon(object):
187 class TestHttpHooksCallbackDaemon(object):
188 def test_hooks_callback_generates_new_port(self, caplog):
188 def test_hooks_callback_generates_new_port(self, caplog):
189 with caplog.at_level(logging.DEBUG):
189 with caplog.at_level(logging.DEBUG):
190 daemon = http_hooks_deamon.HttpHooksCallbackDaemon(host='127.0.0.1', port=8881)
190 daemon = http_hooks_deamon.HttpHooksCallbackDaemon(host='127.0.0.1', port=8881)
191 assert daemon._daemon.server_address == ('127.0.0.1', 8881)
191 assert daemon._daemon.server_address == ('127.0.0.1', 8881)
192
192
193 with caplog.at_level(logging.DEBUG):
193 with caplog.at_level(logging.DEBUG):
194 daemon = http_hooks_deamon.HttpHooksCallbackDaemon(host=None, port=None)
194 daemon = http_hooks_deamon.HttpHooksCallbackDaemon(host=None, port=None)
195 assert daemon._daemon.server_address[1] in range(0, 66000)
195 assert daemon._daemon.server_address[1] in range(0, 66000)
196 assert daemon._daemon.server_address[0] != '127.0.0.1'
196 assert daemon._daemon.server_address[0] != '127.0.0.1'
197
197
198 def test_prepare_inits_daemon_variable(self, tcp_server, caplog):
198 def test_prepare_inits_daemon_variable(self, tcp_server, caplog):
199 with self._tcp_patcher(tcp_server), caplog.at_level(logging.DEBUG):
199 with self._tcp_patcher(tcp_server), caplog.at_level(logging.DEBUG):
200 daemon = http_hooks_deamon.HttpHooksCallbackDaemon(host='127.0.0.1', port=8881)
200 daemon = http_hooks_deamon.HttpHooksCallbackDaemon(host='127.0.0.1', port=8881)
201 assert daemon._daemon == tcp_server
201 assert daemon._daemon == tcp_server
202
202
203 _, port = tcp_server.server_address
203 _, port = tcp_server.server_address
204
204
205 msg = f"HOOKS: 127.0.0.1:{port} Preparing HTTP callback daemon registering " \
205 msg = f"HOOKS: 127.0.0.1:{port} Preparing HTTP callback daemon registering " \
206 f"hook object: <class 'rhodecode.lib.hook_daemon.http_hooks_deamon.HooksHttpHandler'>"
206 f"hook object: <class 'rhodecode.lib.hook_daemon.http_hooks_deamon.HooksHttpHandler'>"
207 assert_message_in_log(
207 assert_message_in_log(
208 caplog.records, msg, levelno=logging.DEBUG, module='http_hooks_deamon')
208 caplog.records, msg, levelno=logging.DEBUG, module='http_hooks_deamon')
209
209
210 def test_prepare_inits_hooks_uri_and_logs_it(
210 def test_prepare_inits_hooks_uri_and_logs_it(
211 self, tcp_server, caplog):
211 self, tcp_server, caplog):
212 with self._tcp_patcher(tcp_server), caplog.at_level(logging.DEBUG):
212 with self._tcp_patcher(tcp_server), caplog.at_level(logging.DEBUG):
213 daemon = http_hooks_deamon.HttpHooksCallbackDaemon(host='127.0.0.1', port=8881)
213 daemon = http_hooks_deamon.HttpHooksCallbackDaemon(host='127.0.0.1', port=8881)
214
214
215 _, port = tcp_server.server_address
215 _, port = tcp_server.server_address
216 expected_uri = '{}:{}'.format('127.0.0.1', port)
216 expected_uri = '{}:{}'.format('127.0.0.1', port)
217 assert daemon.hooks_uri == expected_uri
217 assert daemon.hooks_uri == expected_uri
218
218
219 msg = f"HOOKS: 127.0.0.1:{port} Preparing HTTP callback daemon registering " \
219 msg = f"HOOKS: 127.0.0.1:{port} Preparing HTTP callback daemon registering " \
220 f"hook object: <class 'rhodecode.lib.hook_daemon.http_hooks_deamon.HooksHttpHandler'>"
220 f"hook object: <class 'rhodecode.lib.hook_daemon.http_hooks_deamon.HooksHttpHandler'>"
221
221
222 assert_message_in_log(
222 assert_message_in_log(
223 caplog.records, msg,
223 caplog.records, msg,
224 levelno=logging.DEBUG, module='http_hooks_deamon')
224 levelno=logging.DEBUG, module='http_hooks_deamon')
225
225
226 def test_run_creates_a_thread(self, tcp_server):
226 def test_run_creates_a_thread(self, tcp_server):
227 thread = mock.Mock()
227 thread = mock.Mock()
228
228
229 with self._tcp_patcher(tcp_server):
229 with self._tcp_patcher(tcp_server):
230 daemon = http_hooks_deamon.HttpHooksCallbackDaemon()
230 daemon = http_hooks_deamon.HttpHooksCallbackDaemon()
231
231
232 with self._thread_patcher(thread) as thread_mock:
232 with self._thread_patcher(thread) as thread_mock:
233 daemon._run()
233 daemon._run()
234
234
235 thread_mock.assert_called_once_with(
235 thread_mock.assert_called_once_with(
236 target=tcp_server.serve_forever,
236 target=tcp_server.serve_forever,
237 kwargs={'poll_interval': daemon.POLL_INTERVAL})
237 kwargs={'poll_interval': daemon.POLL_INTERVAL})
238 assert thread.daemon is True
238 assert thread.daemon is True
239 thread.start.assert_called_once_with()
239 thread.start.assert_called_once_with()
240
240
241 def test_run_logs(self, tcp_server, caplog):
241 def test_run_logs(self, tcp_server, caplog):
242
242
243 with self._tcp_patcher(tcp_server):
243 with self._tcp_patcher(tcp_server):
244 daemon = http_hooks_deamon.HttpHooksCallbackDaemon()
244 daemon = http_hooks_deamon.HttpHooksCallbackDaemon()
245
245
246 with self._thread_patcher(mock.Mock()), caplog.at_level(logging.DEBUG):
246 with self._thread_patcher(mock.Mock()), caplog.at_level(logging.DEBUG):
247 daemon._run()
247 daemon._run()
248
248
249 assert_message_in_log(
249 assert_message_in_log(
250 caplog.records,
250 caplog.records,
251 'Running thread-based loop of callback daemon in background',
251 'Running thread-based loop of callback daemon in background',
252 levelno=logging.DEBUG, module='http_hooks_deamon')
252 levelno=logging.DEBUG, module='http_hooks_deamon')
253
253
254 def test_stop_cleans_up_the_connection(self, tcp_server, caplog):
254 def test_stop_cleans_up_the_connection(self, tcp_server, caplog):
255 thread = mock.Mock()
255 thread = mock.Mock()
256
256
257 with self._tcp_patcher(tcp_server):
257 with self._tcp_patcher(tcp_server):
258 daemon = http_hooks_deamon.HttpHooksCallbackDaemon()
258 daemon = http_hooks_deamon.HttpHooksCallbackDaemon()
259
259
260 with self._thread_patcher(thread), caplog.at_level(logging.DEBUG):
260 with self._thread_patcher(thread), caplog.at_level(logging.DEBUG):
261 with daemon:
261 with daemon:
262 assert daemon._daemon == tcp_server
262 assert daemon._daemon == tcp_server
263 assert daemon._callback_thread == thread
263 assert daemon._callback_thread == thread
264
264
265 assert daemon._daemon is None
265 assert daemon._daemon is None
266 assert daemon._callback_thread is None
266 assert daemon._callback_thread is None
267 tcp_server.shutdown.assert_called_with()
267 tcp_server.shutdown.assert_called_with()
268 thread.join.assert_called_once_with()
268 thread.join.assert_called_once_with()
269
269
270 assert_message_in_log(
270 assert_message_in_log(
271 caplog.records, 'Waiting for background thread to finish.',
271 caplog.records, 'Waiting for background thread to finish.',
272 levelno=logging.DEBUG, module='http_hooks_deamon')
272 levelno=logging.DEBUG, module='http_hooks_deamon')
273
273
274 def _tcp_patcher(self, tcp_server):
274 def _tcp_patcher(self, tcp_server):
275 return mock.patch.object(
275 return mock.patch.object(
276 http_hooks_deamon, 'TCPServer', return_value=tcp_server)
276 http_hooks_deamon, 'TCPServer', return_value=tcp_server)
277
277
278 def _thread_patcher(self, thread):
278 def _thread_patcher(self, thread):
279 return mock.patch.object(
279 return mock.patch.object(
280 http_hooks_deamon.threading, 'Thread', return_value=thread)
280 http_hooks_deamon.threading, 'Thread', return_value=thread)
281
281
282
282
283 class TestPrepareHooksDaemon(object):
283 class TestPrepareHooksDaemon(object):
284
284
285 @pytest.mark.parametrize('protocol', ('celery',))
285 @pytest.mark.parametrize('protocol', ('celery',))
286 def test_returns_celery_hooks_callback_daemon_when_celery_protocol_specified(
286 def test_returns_celery_hooks_callback_daemon_when_celery_protocol_specified(
287 self, protocol):
287 self, protocol):
288 with tempfile.NamedTemporaryFile(mode='w') as temp_file:
288 with tempfile.NamedTemporaryFile(mode='w') as temp_file:
289 temp_file.write("[app:main]\ncelery.broker_url = redis://redis/0\n"
289 temp_file.write("[app:main]\ncelery.broker_url = redis://redis/0\n"
290 "celery.result_backend = redis://redis/0")
290 "celery.result_backend = redis://redis/0")
291 temp_file.flush()
291 temp_file.flush()
292 expected_extras = {'config': temp_file.name}
292 expected_extras = {'config': temp_file.name}
293 callback, extras = hook_base.prepare_callback_daemon(
293 callback, extras = hook_base.prepare_callback_daemon(
294 expected_extras, protocol=protocol, host='')
294 expected_extras, protocol=protocol, host='')
295 assert isinstance(callback, celery_hooks_deamon.CeleryHooksCallbackDaemon)
295 assert isinstance(callback, celery_hooks_deamon.CeleryHooksCallbackDaemon)
296
296
297 @pytest.mark.parametrize('protocol, expected_class', (
297 @pytest.mark.parametrize('protocol, expected_class', (
298 ('http', http_hooks_deamon.HttpHooksCallbackDaemon),
298 ('http', http_hooks_deamon.HttpHooksCallbackDaemon),
299 ))
299 ))
300 def test_returns_real_hooks_callback_daemon_when_protocol_is_specified(
300 def test_returns_real_hooks_callback_daemon_when_protocol_is_specified(
301 self, protocol, expected_class):
301 self, protocol, expected_class):
302 expected_extras = {
302 expected_extras = {
303 'extra1': 'value1',
303 'extra1': 'value1',
304 'txn_id': 'txnid2',
304 'txn_id': 'txnid2',
305 'hooks_protocol': protocol.lower(),
305 'hooks_protocol': protocol.lower(),
306 'task_backend': '',
306 'task_backend': '',
307 'task_queue': '',
307 'task_queue': '',
308 'repo_store': '/var/opt/rhodecode_repo_store'
308 'repo_store': '/var/opt/rhodecode_repo_store',
309 'repository': 'rhodecode',
309 }
310 }
311 from rhodecode import CONFIG
312 CONFIG['vcs.svn.redis_conn'] = 'redis://redis:6379/0'
310 callback, extras = hook_base.prepare_callback_daemon(
313 callback, extras = hook_base.prepare_callback_daemon(
311 expected_extras.copy(), protocol=protocol, host='127.0.0.1',
314 expected_extras.copy(), protocol=protocol, host='127.0.0.1',
312 txn_id='txnid2')
315 txn_id='txnid2')
313 assert isinstance(callback, expected_class)
316 assert isinstance(callback, expected_class)
314 extras.pop('hooks_uri')
317 extras.pop('hooks_uri')
315 expected_extras['time'] = extras['time']
318 expected_extras['time'] = extras['time']
316 assert extras == expected_extras
319 assert extras == expected_extras
317
320
318 @pytest.mark.parametrize('protocol', (
321 @pytest.mark.parametrize('protocol', (
319 'invalid',
322 'invalid',
320 'Http',
323 'Http',
321 'HTTP',
324 'HTTP',
322 ))
325 ))
323 def test_raises_on_invalid_protocol(self, protocol):
326 def test_raises_on_invalid_protocol(self, protocol):
324 expected_extras = {
327 expected_extras = {
325 'extra1': 'value1',
328 'extra1': 'value1',
326 'hooks_protocol': protocol.lower()
329 'hooks_protocol': protocol.lower()
327 }
330 }
328 with pytest.raises(Exception):
331 with pytest.raises(Exception):
329 callback, extras = hook_base.prepare_callback_daemon(
332 callback, extras = hook_base.prepare_callback_daemon(
330 expected_extras.copy(),
333 expected_extras.copy(),
331 protocol=protocol, host='127.0.0.1')
334 protocol=protocol, host='127.0.0.1')
332
335
333
336
334 class MockRequest(object):
337 class MockRequest(object):
335
338
336 def __init__(self, request):
339 def __init__(self, request):
337 self.request = request
340 self.request = request
338 self.input_stream = io.BytesIO(safe_bytes(self.request))
341 self.input_stream = io.BytesIO(safe_bytes(self.request))
339 self.output_stream = io.BytesIO() # make it un-closable for testing invesitagion
342 self.output_stream = io.BytesIO() # make it un-closable for testing invesitagion
340 self.output_stream.close = lambda: None
343 self.output_stream.close = lambda: None
341
344
342 def makefile(self, mode, *args, **kwargs):
345 def makefile(self, mode, *args, **kwargs):
343 return self.output_stream if mode == 'wb' else self.input_stream
346 return self.output_stream if mode == 'wb' else self.input_stream
344
347
345
348
346 class MockServer(object):
349 class MockServer(object):
347
350
348 def __init__(self, handler_cls, request):
351 def __init__(self, handler_cls, request):
349 ip_port = ('0.0.0.0', 8888)
352 ip_port = ('0.0.0.0', 8888)
350 self.request = MockRequest(request)
353 self.request = MockRequest(request)
351 self.server_address = ip_port
354 self.server_address = ip_port
352 self.handler = handler_cls(self.request, ip_port, self)
355 self.handler = handler_cls(self.request, ip_port, self)
353
356
354
357
355 @pytest.fixture()
358 @pytest.fixture()
356 def tcp_server():
359 def tcp_server():
357 server = mock.Mock()
360 server = mock.Mock()
358 server.server_address = ('127.0.0.1', 8881)
361 server.server_address = ('127.0.0.1', 8881)
359 server.wbufsize = 1024
362 server.wbufsize = 1024
360 return server
363 return server
General Comments 0
You need to be logged in to leave comments. Login now