##// END OF EJS Templates
tests: test fixes after py311 compat run
super-admin -
r1115:508a6554 python3
parent child Browse files
Show More
@@ -1,103 +1,103 b''
1 #SHELL = /bin/bash
1 #SHELL = /bin/bash
2
2
3 # set by: PATH_TO_OUTDATED_PACKAGES=/some/path/outdated_packages.py
3 # set by: PATH_TO_OUTDATED_PACKAGES=/some/path/outdated_packages.py
4 OUTDATED_PACKAGES = ${PATH_TO_OUTDATED_PACKAGES}
4 OUTDATED_PACKAGES = ${PATH_TO_OUTDATED_PACKAGES}
5
5
6 .PHONY: clean
6 .PHONY: clean
7 ## Cleanup compiled and cache py files
7 ## Cleanup compiled and cache py files
8 clean:
8 clean:
9 make test-clean
9 make test-clean
10 find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' -o -iname '*.orig' \) -exec rm '{}' ';'
10 find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' -o -iname '*.orig' \) -exec rm '{}' ';'
11
11
12
12
13 .PHONY: test
13 .PHONY: test
14 ## run test-clean and tests
14 ## run test-clean and tests
15 test:
15 test:
16 make test-clean
16 make test-clean
17 make test-only
17 make test-only
18
18
19
19
20 .PHONY: test-clean
20 .PHONY: test-clean
21 ## run test-clean and tests
21 ## run test-clean and tests
22 test-clean:
22 test-clean:
23 rm -rf coverage.xml htmlcov junit.xml pylint.log result
23 rm -rf coverage.xml htmlcov junit.xml pylint.log result
24 find . -type d -name "__pycache__" -prune -exec rm -rf '{}' ';'
24 find . -type d -name "__pycache__" -prune -exec rm -rf '{}' ';'
25 find . -type f \( -iname '.coverage.*' \) -exec rm '{}' ';'
25 find . -type f \( -iname '.coverage.*' \) -exec rm '{}' ';'
26
26
27
27
28 .PHONY: test-only
28 .PHONY: test-only
29 ## Run tests only without cleanup
29 ## Run tests only without cleanup
30 test-only:
30 test-only:
31 PYTHONHASHSEED=random \
31 PYTHONHASHSEED=random \
32 py.test -x -vv -r xw -p no:sugar \
32 py.test -x -vv -r xw -p no:sugar \
33 --cov-report=term-missing --cov-report=html --cov=vcsserver vcsserver
33 --cov-report=term-missing --cov-report=html --cov=vcsserver vcsserver
34
34
35
35
36 .PHONY: pip-packages
36 .PHONY: pip-packages
37 ## Show outdated packages
37 ## Show outdated packages
38 pip-packages:
38 pip-packages:
39 python ${OUTDATED_PACKAGES}
39 python ${OUTDATED_PACKAGES}
40
40
41
41
42 .PHONY: build
42 .PHONY: build
43 ## Build sdist/egg
43 ## Build sdist/egg
44 build:
44 build:
45 python -m build
45 python -m build
46
46
47
47
48 .PHONY: dev-env
48 .PHONY: dev-env
49 ## make dev-env based on the requirements files and install develop of packages
49 ## make dev-env based on the requirements files and install develop of packages
50 dev-env:
50 dev-env:
51 pip install build virtualenv pipdeptree
51 pip install build virtualenv
52 pip wheel --wheel-dir=/home/rhodecode/.cache/pip/wheels -r requirements.txt -r requirements_test.txt -r requirements_debug.txt
52 pip wheel --wheel-dir=/home/rhodecode/.cache/pip/wheels -r requirements.txt -r requirements_test.txt -r requirements_debug.txt
53 pip install --no-index --find-links=/home/rhodecode/.cache/pip/wheels -r requirements.txt -r requirements_test.txt -r requirements_debug.txt
53 pip install --no-index --find-links=/home/rhodecode/.cache/pip/wheels -r requirements.txt -r requirements_test.txt -r requirements_debug.txt
54 pip install -e .
54 pip install -e .
55
55
56
56
57 .PHONY: dev-srv
57 .PHONY: dev-srv
58 ## run develop server instance
58 ## run develop server instance
59 dev-srv:
59 dev-srv:
60 pserve --reload .dev/dev.ini
60 pserve --reload .dev/dev.ini
61
61
62
62
63 # Default command on calling make
63 # Default command on calling make
64 .DEFAULT_GOAL := show-help
64 .DEFAULT_GOAL := show-help
65
65
66 .PHONY: show-help
66 .PHONY: show-help
67 show-help:
67 show-help:
68 @echo "$$(tput bold)Available rules:$$(tput sgr0)"
68 @echo "$$(tput bold)Available rules:$$(tput sgr0)"
69 @echo
69 @echo
70 @sed -n -e "/^## / { \
70 @sed -n -e "/^## / { \
71 h; \
71 h; \
72 s/.*//; \
72 s/.*//; \
73 :doc" \
73 :doc" \
74 -e "H; \
74 -e "H; \
75 n; \
75 n; \
76 s/^## //; \
76 s/^## //; \
77 t doc" \
77 t doc" \
78 -e "s/:.*//; \
78 -e "s/:.*//; \
79 G; \
79 G; \
80 s/\\n## /---/; \
80 s/\\n## /---/; \
81 s/\\n/ /g; \
81 s/\\n/ /g; \
82 p; \
82 p; \
83 }" ${MAKEFILE_LIST} \
83 }" ${MAKEFILE_LIST} \
84 | LC_ALL='C' sort --ignore-case \
84 | LC_ALL='C' sort --ignore-case \
85 | awk -F '---' \
85 | awk -F '---' \
86 -v ncol=$$(tput cols) \
86 -v ncol=$$(tput cols) \
87 -v indent=19 \
87 -v indent=19 \
88 -v col_on="$$(tput setaf 6)" \
88 -v col_on="$$(tput setaf 6)" \
89 -v col_off="$$(tput sgr0)" \
89 -v col_off="$$(tput sgr0)" \
90 '{ \
90 '{ \
91 printf "%s%*s%s ", col_on, -indent, $$1, col_off; \
91 printf "%s%*s%s ", col_on, -indent, $$1, col_off; \
92 n = split($$2, words, " "); \
92 n = split($$2, words, " "); \
93 line_length = ncol - indent; \
93 line_length = ncol - indent; \
94 for (i = 1; i <= n; i++) { \
94 for (i = 1; i <= n; i++) { \
95 line_length -= length(words[i]) + 1; \
95 line_length -= length(words[i]) + 1; \
96 if (line_length <= 0) { \
96 if (line_length <= 0) { \
97 line_length = ncol - indent - length(words[i]) - 1; \
97 line_length = ncol - indent - length(words[i]) - 1; \
98 printf "\n%*s ", -indent, " "; \
98 printf "\n%*s ", -indent, " "; \
99 } \
99 } \
100 printf "%s ", words[i]; \
100 printf "%s ", words[i]; \
101 } \
101 } \
102 printf "\n"; \
102 printf "\n"; \
103 }'
103 }'
@@ -1,12 +1,22 b''
1 ## special libraries we could extend the requirements.txt file with to add some
1 ## special libraries we could extend the requirements.txt file with to add some
2 ## custom libraries useful for debug and memory tracing
2 ## custom libraries usefull for debug and memory tracing
3
4 ## uncomment inclusion of this file in requirements.txt run make generate-pkgs and nix-shell
5
3
6 objgraph
4 objgraph
7 memory-profiler
5 memory-profiler
8 pympler
6 pympler
7
8 ## debug
9 ipdb
9 ipdb
10 ipython
10 ipython
11 rich
12
13 # format
11 flake8
14 flake8
12 rich
15 ruff
16
17 pipdeptree==2.7.1
18 invoke==2.0.0
19 bumpversion==0.6.0
20 bump2version==1.0.1
21
22 docutils-stubs
@@ -1,286 +1,286 b''
1 # RhodeCode VCSServer provides access to different vcs backends via network.
1 # RhodeCode VCSServer provides access to different vcs backends via network.
2 # Copyright (C) 2014-2020 RhodeCode GmbH
2 # Copyright (C) 2014-2020 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 General Public License as published by
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
7 # (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
18 import threading
18 import threading
19 import msgpack
19 import msgpack
20
20
21 from http.server import BaseHTTPRequestHandler
21 from http.server import BaseHTTPRequestHandler
22 from socketserver import TCPServer
22 from socketserver import TCPServer
23
23
24 import mercurial.ui
24 import mercurial.ui
25 import mock
25 import mock
26 import pytest
26 import pytest
27
27
28 from vcsserver.hooks import HooksHttpClient
28 from vcsserver.hooks import HooksHttpClient
29 from vcsserver.lib.rc_json import json
29 from vcsserver.lib.rc_json import json
30 from vcsserver import hooks
30 from vcsserver import hooks
31
31
32
32
33 def get_hg_ui(extras=None):
33 def get_hg_ui(extras=None):
34 """Create a Config object with a valid RC_SCM_DATA entry."""
34 """Create a Config object with a valid RC_SCM_DATA entry."""
35 extras = extras or {}
35 extras = extras or {}
36 required_extras = {
36 required_extras = {
37 'username': '',
37 'username': '',
38 'repository': '',
38 'repository': '',
39 'locked_by': '',
39 'locked_by': '',
40 'scm': '',
40 'scm': '',
41 'make_lock': '',
41 'make_lock': '',
42 'action': '',
42 'action': '',
43 'ip': '',
43 'ip': '',
44 'hooks_uri': 'fake_hooks_uri',
44 'hooks_uri': 'fake_hooks_uri',
45 }
45 }
46 required_extras.update(extras)
46 required_extras.update(extras)
47 hg_ui = mercurial.ui.ui()
47 hg_ui = mercurial.ui.ui()
48 hg_ui.setconfig(b'rhodecode', b'RC_SCM_DATA', json.dumps(required_extras))
48 hg_ui.setconfig(b'rhodecode', b'RC_SCM_DATA', json.dumps(required_extras))
49
49
50 return hg_ui
50 return hg_ui
51
51
52
52
53 def test_git_pre_receive_is_disabled():
53 def test_git_pre_receive_is_disabled():
54 extras = {'hooks': ['pull']}
54 extras = {'hooks': ['pull']}
55 response = hooks.git_pre_receive(None, None,
55 response = hooks.git_pre_receive(None, None,
56 {'RC_SCM_DATA': json.dumps(extras)})
56 {'RC_SCM_DATA': json.dumps(extras)})
57
57
58 assert response == 0
58 assert response == 0
59
59
60
60
61 def test_git_post_receive_is_disabled():
61 def test_git_post_receive_is_disabled():
62 extras = {'hooks': ['pull']}
62 extras = {'hooks': ['pull']}
63 response = hooks.git_post_receive(None, '',
63 response = hooks.git_post_receive(None, '',
64 {'RC_SCM_DATA': json.dumps(extras)})
64 {'RC_SCM_DATA': json.dumps(extras)})
65
65
66 assert response == 0
66 assert response == 0
67
67
68
68
69 def test_git_post_receive_calls_repo_size():
69 def test_git_post_receive_calls_repo_size():
70 extras = {'hooks': ['push', 'repo_size']}
70 extras = {'hooks': ['push', 'repo_size']}
71
71
72 with mock.patch.object(hooks, '_call_hook') as call_hook_mock:
72 with mock.patch.object(hooks, '_call_hook') as call_hook_mock:
73 hooks.git_post_receive(
73 hooks.git_post_receive(
74 None, '', {'RC_SCM_DATA': json.dumps(extras)})
74 None, '', {'RC_SCM_DATA': json.dumps(extras)})
75 extras.update({'commit_ids': [], 'hook_type': 'post_receive',
75 extras.update({'commit_ids': [], 'hook_type': 'post_receive',
76 'new_refs': {'bookmarks': [], 'branches': [], 'tags': []}})
76 'new_refs': {'bookmarks': [], 'branches': [], 'tags': []}})
77 expected_calls = [
77 expected_calls = [
78 mock.call('repo_size', extras, mock.ANY),
78 mock.call('repo_size', extras, mock.ANY),
79 mock.call('post_push', extras, mock.ANY),
79 mock.call('post_push', extras, mock.ANY),
80 ]
80 ]
81 assert call_hook_mock.call_args_list == expected_calls
81 assert call_hook_mock.call_args_list == expected_calls
82
82
83
83
84 def test_git_post_receive_does_not_call_disabled_repo_size():
84 def test_git_post_receive_does_not_call_disabled_repo_size():
85 extras = {'hooks': ['push']}
85 extras = {'hooks': ['push']}
86
86
87 with mock.patch.object(hooks, '_call_hook') as call_hook_mock:
87 with mock.patch.object(hooks, '_call_hook') as call_hook_mock:
88 hooks.git_post_receive(
88 hooks.git_post_receive(
89 None, '', {'RC_SCM_DATA': json.dumps(extras)})
89 None, '', {'RC_SCM_DATA': json.dumps(extras)})
90 extras.update({'commit_ids': [], 'hook_type': 'post_receive',
90 extras.update({'commit_ids': [], 'hook_type': 'post_receive',
91 'new_refs': {'bookmarks': [], 'branches': [], 'tags': []}})
91 'new_refs': {'bookmarks': [], 'branches': [], 'tags': []}})
92 expected_calls = [
92 expected_calls = [
93 mock.call('post_push', extras, mock.ANY)
93 mock.call('post_push', extras, mock.ANY)
94 ]
94 ]
95 assert call_hook_mock.call_args_list == expected_calls
95 assert call_hook_mock.call_args_list == expected_calls
96
96
97
97
98 def test_repo_size_exception_does_not_affect_git_post_receive():
98 def test_repo_size_exception_does_not_affect_git_post_receive():
99 extras = {'hooks': ['push', 'repo_size']}
99 extras = {'hooks': ['push', 'repo_size']}
100 status = 0
100 status = 0
101
101
102 def side_effect(name, *args, **kwargs):
102 def side_effect(name, *args, **kwargs):
103 if name == 'repo_size':
103 if name == 'repo_size':
104 raise Exception('Fake exception')
104 raise Exception('Fake exception')
105 else:
105 else:
106 return status
106 return status
107
107
108 with mock.patch.object(hooks, '_call_hook') as call_hook_mock:
108 with mock.patch.object(hooks, '_call_hook') as call_hook_mock:
109 call_hook_mock.side_effect = side_effect
109 call_hook_mock.side_effect = side_effect
110 result = hooks.git_post_receive(
110 result = hooks.git_post_receive(
111 None, '', {'RC_SCM_DATA': json.dumps(extras)})
111 None, '', {'RC_SCM_DATA': json.dumps(extras)})
112 assert result == status
112 assert result == status
113
113
114
114
115 def test_git_pre_pull_is_disabled():
115 def test_git_pre_pull_is_disabled():
116 assert hooks.git_pre_pull({'hooks': ['push']}) == hooks.HookResponse(0, '')
116 assert hooks.git_pre_pull({'hooks': ['push']}) == hooks.HookResponse(0, '')
117
117
118
118
119 def test_git_post_pull_is_disabled():
119 def test_git_post_pull_is_disabled():
120 assert (
120 assert (
121 hooks.git_post_pull({'hooks': ['push']}) == hooks.HookResponse(0, ''))
121 hooks.git_post_pull({'hooks': ['push']}) == hooks.HookResponse(0, ''))
122
122
123
123
124 class TestGetHooksClient(object):
124 class TestGetHooksClient(object):
125
125
126 def test_returns_http_client_when_protocol_matches(self):
126 def test_returns_http_client_when_protocol_matches(self):
127 hooks_uri = 'localhost:8000'
127 hooks_uri = 'localhost:8000'
128 result = hooks._get_hooks_client({
128 result = hooks._get_hooks_client({
129 'hooks_uri': hooks_uri,
129 'hooks_uri': hooks_uri,
130 'hooks_protocol': 'http'
130 'hooks_protocol': 'http'
131 })
131 })
132 assert isinstance(result, hooks.HooksHttpClient)
132 assert isinstance(result, hooks.HooksHttpClient)
133 assert result.hooks_uri == hooks_uri
133 assert result.hooks_uri == hooks_uri
134
134
135 def test_returns_dummy_client_when_hooks_uri_not_specified(self):
135 def test_returns_dummy_client_when_hooks_uri_not_specified(self):
136 fake_module = mock.Mock()
136 fake_module = mock.Mock()
137 import_patcher = mock.patch.object(
137 import_patcher = mock.patch.object(
138 hooks.importlib, 'import_module', return_value=fake_module)
138 hooks.importlib, 'import_module', return_value=fake_module)
139 fake_module_name = 'fake.module'
139 fake_module_name = 'fake.module'
140 with import_patcher as import_mock:
140 with import_patcher as import_mock:
141 result = hooks._get_hooks_client(
141 result = hooks._get_hooks_client(
142 {'hooks_module': fake_module_name})
142 {'hooks_module': fake_module_name})
143
143
144 import_mock.assert_called_once_with(fake_module_name)
144 import_mock.assert_called_once_with(fake_module_name)
145 assert isinstance(result, hooks.HooksDummyClient)
145 assert isinstance(result, hooks.HooksDummyClient)
146 assert result._hooks_module == fake_module
146 assert result._hooks_module == fake_module
147
147
148
148
149 class TestHooksHttpClient(object):
149 class TestHooksHttpClient(object):
150 def test_init_sets_hooks_uri(self):
150 def test_init_sets_hooks_uri(self):
151 uri = 'localhost:3000'
151 uri = 'localhost:3000'
152 client = hooks.HooksHttpClient(uri)
152 client = hooks.HooksHttpClient(uri)
153 assert client.hooks_uri == uri
153 assert client.hooks_uri == uri
154
154
155 def test_serialize_returns_serialized_string(self):
155 def test_serialize_returns_serialized_string(self):
156 client = hooks.HooksHttpClient('localhost:3000')
156 client = hooks.HooksHttpClient('localhost:3000')
157 hook_name = 'test'
157 hook_name = 'test'
158 extras = {
158 extras = {
159 'first': 1,
159 'first': 1,
160 'second': 'two'
160 'second': 'two'
161 }
161 }
162 hooks_proto, result = client._serialize(hook_name, extras)
162 hooks_proto, result = client._serialize(hook_name, extras)
163 expected_result = msgpack.packb({
163 expected_result = msgpack.packb({
164 'method': hook_name,
164 'method': hook_name,
165 'extras': extras,
165 'extras': extras,
166 })
166 })
167 assert hooks_proto == {'rc-hooks-protocol': 'msgpack.v1'}
167 assert hooks_proto == {'rc-hooks-protocol': 'msgpack.v1', 'Connection': 'keep-alive'}
168 assert result == expected_result
168 assert result == expected_result
169
169
170 def test_call_queries_http_server(self, http_mirror):
170 def test_call_queries_http_server(self, http_mirror):
171 client = hooks.HooksHttpClient(http_mirror.uri)
171 client = hooks.HooksHttpClient(http_mirror.uri)
172 hook_name = 'test'
172 hook_name = 'test'
173 extras = {
173 extras = {
174 'first': 1,
174 'first': 1,
175 'second': 'two'
175 'second': 'two'
176 }
176 }
177 result = client(hook_name, extras)
177 result = client(hook_name, extras)
178 expected_result = msgpack.unpackb(msgpack.packb({
178 expected_result = msgpack.unpackb(msgpack.packb({
179 'method': hook_name,
179 'method': hook_name,
180 'extras': extras
180 'extras': extras
181 }), raw=False)
181 }), raw=False)
182 assert result == expected_result
182 assert result == expected_result
183
183
184
184
185 class TestHooksDummyClient(object):
185 class TestHooksDummyClient(object):
186 def test_init_imports_hooks_module(self):
186 def test_init_imports_hooks_module(self):
187 hooks_module_name = 'rhodecode.fake.module'
187 hooks_module_name = 'rhodecode.fake.module'
188 hooks_module = mock.MagicMock()
188 hooks_module = mock.MagicMock()
189
189
190 import_patcher = mock.patch.object(
190 import_patcher = mock.patch.object(
191 hooks.importlib, 'import_module', return_value=hooks_module)
191 hooks.importlib, 'import_module', return_value=hooks_module)
192 with import_patcher as import_mock:
192 with import_patcher as import_mock:
193 client = hooks.HooksDummyClient(hooks_module_name)
193 client = hooks.HooksDummyClient(hooks_module_name)
194 import_mock.assert_called_once_with(hooks_module_name)
194 import_mock.assert_called_once_with(hooks_module_name)
195 assert client._hooks_module == hooks_module
195 assert client._hooks_module == hooks_module
196
196
197 def test_call_returns_hook_result(self):
197 def test_call_returns_hook_result(self):
198 hooks_module_name = 'rhodecode.fake.module'
198 hooks_module_name = 'rhodecode.fake.module'
199 hooks_module = mock.MagicMock()
199 hooks_module = mock.MagicMock()
200 import_patcher = mock.patch.object(
200 import_patcher = mock.patch.object(
201 hooks.importlib, 'import_module', return_value=hooks_module)
201 hooks.importlib, 'import_module', return_value=hooks_module)
202 with import_patcher:
202 with import_patcher:
203 client = hooks.HooksDummyClient(hooks_module_name)
203 client = hooks.HooksDummyClient(hooks_module_name)
204
204
205 result = client('post_push', {})
205 result = client('post_push', {})
206 hooks_module.Hooks.assert_called_once_with()
206 hooks_module.Hooks.assert_called_once_with()
207 assert result == hooks_module.Hooks().__enter__().post_push()
207 assert result == hooks_module.Hooks().__enter__().post_push()
208
208
209
209
210 @pytest.fixture
210 @pytest.fixture
211 def http_mirror(request):
211 def http_mirror(request):
212 server = MirrorHttpServer()
212 server = MirrorHttpServer()
213 request.addfinalizer(server.stop)
213 request.addfinalizer(server.stop)
214 return server
214 return server
215
215
216
216
217 class MirrorHttpHandler(BaseHTTPRequestHandler):
217 class MirrorHttpHandler(BaseHTTPRequestHandler):
218
218
219 def do_POST(self):
219 def do_POST(self):
220 length = int(self.headers['Content-Length'])
220 length = int(self.headers['Content-Length'])
221 body = self.rfile.read(length)
221 body = self.rfile.read(length)
222 self.send_response(200)
222 self.send_response(200)
223 self.end_headers()
223 self.end_headers()
224 self.wfile.write(body)
224 self.wfile.write(body)
225
225
226
226
227 class MirrorHttpServer(object):
227 class MirrorHttpServer(object):
228 ip_address = '127.0.0.1'
228 ip_address = '127.0.0.1'
229 port = 0
229 port = 0
230
230
231 def __init__(self):
231 def __init__(self):
232 self._daemon = TCPServer((self.ip_address, 0), MirrorHttpHandler)
232 self._daemon = TCPServer((self.ip_address, 0), MirrorHttpHandler)
233 _, self.port = self._daemon.server_address
233 _, self.port = self._daemon.server_address
234 self._thread = threading.Thread(target=self._daemon.serve_forever)
234 self._thread = threading.Thread(target=self._daemon.serve_forever)
235 self._thread.daemon = True
235 self._thread.daemon = True
236 self._thread.start()
236 self._thread.start()
237
237
238 def stop(self):
238 def stop(self):
239 self._daemon.shutdown()
239 self._daemon.shutdown()
240 self._thread.join()
240 self._thread.join()
241 self._daemon = None
241 self._daemon = None
242 self._thread = None
242 self._thread = None
243
243
244 @property
244 @property
245 def uri(self):
245 def uri(self):
246 return '{}:{}'.format(self.ip_address, self.port)
246 return '{}:{}'.format(self.ip_address, self.port)
247
247
248
248
249 def test_hooks_http_client_init():
249 def test_hooks_http_client_init():
250 hooks_uri = 'http://localhost:8000'
250 hooks_uri = 'http://localhost:8000'
251 client = HooksHttpClient(hooks_uri)
251 client = HooksHttpClient(hooks_uri)
252 assert client.hooks_uri == hooks_uri
252 assert client.hooks_uri == hooks_uri
253
253
254
254
255 def test_hooks_http_client_call():
255 def test_hooks_http_client_call():
256 hooks_uri = 'http://localhost:8000'
256 hooks_uri = 'http://localhost:8000'
257
257
258 method = 'test_method'
258 method = 'test_method'
259 extras = {'key': 'value'}
259 extras = {'key': 'value'}
260
260
261 with \
261 with \
262 mock.patch('vcsserver.hooks.HTTPConnection') as mock_connection,\
262 mock.patch('http.client.HTTPConnection') as mock_connection,\
263 mock.patch('msgpack.load') as mock_load:
263 mock.patch('msgpack.load') as mock_load:
264
264
265 client = HooksHttpClient(hooks_uri)
265 client = HooksHttpClient(hooks_uri)
266
266
267 mock_load.return_value = {'result': 'success'}
267 mock_load.return_value = {'result': 'success'}
268 response = mock.MagicMock()
268 response = mock.MagicMock()
269 response.status = 200
269 response.status = 200
270 mock_connection.request.side_effect = None
270 mock_connection.request.side_effect = None
271 mock_connection.getresponse.return_value = response
271 mock_connection.getresponse.return_value = response
272
272
273 result = client(method, extras)
273 result = client(method, extras)
274
274
275 mock_connection.assert_called_with(hooks_uri)
275 mock_connection.assert_called_with(hooks_uri)
276 mock_connection.return_value.request.assert_called_once()
276 mock_connection.return_value.request.assert_called_once()
277 assert result == {'result': 'success'}
277 assert result == {'result': 'success'}
278
278
279
279
280 def test_hooks_http_client_serialize():
280 def test_hooks_http_client_serialize():
281 method = 'test_method'
281 method = 'test_method'
282 extras = {'key': 'value'}
282 extras = {'key': 'value'}
283 headers, body = HooksHttpClient._serialize(method, extras)
283 headers, body = HooksHttpClient._serialize(method, extras)
284
284
285 assert headers == {'rc-hooks-protocol': HooksHttpClient.proto}
285 assert headers == {'rc-hooks-protocol': HooksHttpClient.proto, 'Connection': 'keep-alive'}
286 assert msgpack.unpackb(body) == {'method': method, 'extras': extras}
286 assert msgpack.unpackb(body) == {'method': method, 'extras': extras}
General Comments 0
You need to be logged in to leave comments. Login now