##// END OF EJS Templates
tests: added few generated tests
super-admin -
r1087:cde6d2b1 python3
parent child Browse files
Show More
@@ -1,245 +1,286 b''
1 1 # RhodeCode VCSServer provides access to different vcs backends via network.
2 2 # Copyright (C) 2014-2020 RhodeCode GmbH
3 3 #
4 4 # This program is free software; you can redistribute it and/or modify
5 5 # it under the terms of the GNU General Public License as published by
6 6 # the Free Software Foundation; either version 3 of the License, or
7 7 # (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software Foundation,
16 16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 17
18 18 import threading
19 19 import msgpack
20 20
21 21 from http.server import BaseHTTPRequestHandler
22 22 from socketserver import TCPServer
23 23
24 24 import mercurial.ui
25 25 import mock
26 26 import pytest
27 27
28 from vcsserver.hooks import HooksHttpClient
28 29 from vcsserver.lib.rc_json import json
29 30 from vcsserver import hooks
30 31
31 32
32 33 def get_hg_ui(extras=None):
33 34 """Create a Config object with a valid RC_SCM_DATA entry."""
34 35 extras = extras or {}
35 36 required_extras = {
36 37 'username': '',
37 38 'repository': '',
38 39 'locked_by': '',
39 40 'scm': '',
40 41 'make_lock': '',
41 42 'action': '',
42 43 'ip': '',
43 44 'hooks_uri': 'fake_hooks_uri',
44 45 }
45 46 required_extras.update(extras)
46 47 hg_ui = mercurial.ui.ui()
47 48 hg_ui.setconfig(b'rhodecode', b'RC_SCM_DATA', json.dumps(required_extras))
48 49
49 50 return hg_ui
50 51
51 52
52 53 def test_git_pre_receive_is_disabled():
53 54 extras = {'hooks': ['pull']}
54 55 response = hooks.git_pre_receive(None, None,
55 56 {'RC_SCM_DATA': json.dumps(extras)})
56 57
57 58 assert response == 0
58 59
59 60
60 61 def test_git_post_receive_is_disabled():
61 62 extras = {'hooks': ['pull']}
62 63 response = hooks.git_post_receive(None, '',
63 64 {'RC_SCM_DATA': json.dumps(extras)})
64 65
65 66 assert response == 0
66 67
67 68
68 69 def test_git_post_receive_calls_repo_size():
69 70 extras = {'hooks': ['push', 'repo_size']}
70 71
71 72 with mock.patch.object(hooks, '_call_hook') as call_hook_mock:
72 73 hooks.git_post_receive(
73 74 None, '', {'RC_SCM_DATA': json.dumps(extras)})
74 75 extras.update({'commit_ids': [], 'hook_type': 'post_receive',
75 76 'new_refs': {'bookmarks': [], 'branches': [], 'tags': []}})
76 77 expected_calls = [
77 78 mock.call('repo_size', extras, mock.ANY),
78 79 mock.call('post_push', extras, mock.ANY),
79 80 ]
80 81 assert call_hook_mock.call_args_list == expected_calls
81 82
82 83
83 84 def test_git_post_receive_does_not_call_disabled_repo_size():
84 85 extras = {'hooks': ['push']}
85 86
86 87 with mock.patch.object(hooks, '_call_hook') as call_hook_mock:
87 88 hooks.git_post_receive(
88 89 None, '', {'RC_SCM_DATA': json.dumps(extras)})
89 90 extras.update({'commit_ids': [], 'hook_type': 'post_receive',
90 91 'new_refs': {'bookmarks': [], 'branches': [], 'tags': []}})
91 92 expected_calls = [
92 93 mock.call('post_push', extras, mock.ANY)
93 94 ]
94 95 assert call_hook_mock.call_args_list == expected_calls
95 96
96 97
97 98 def test_repo_size_exception_does_not_affect_git_post_receive():
98 99 extras = {'hooks': ['push', 'repo_size']}
99 100 status = 0
100 101
101 102 def side_effect(name, *args, **kwargs):
102 103 if name == 'repo_size':
103 104 raise Exception('Fake exception')
104 105 else:
105 106 return status
106 107
107 108 with mock.patch.object(hooks, '_call_hook') as call_hook_mock:
108 109 call_hook_mock.side_effect = side_effect
109 110 result = hooks.git_post_receive(
110 111 None, '', {'RC_SCM_DATA': json.dumps(extras)})
111 112 assert result == status
112 113
113 114
114 115 def test_git_pre_pull_is_disabled():
115 116 assert hooks.git_pre_pull({'hooks': ['push']}) == hooks.HookResponse(0, '')
116 117
117 118
118 119 def test_git_post_pull_is_disabled():
119 120 assert (
120 121 hooks.git_post_pull({'hooks': ['push']}) == hooks.HookResponse(0, ''))
121 122
122 123
123 124 class TestGetHooksClient(object):
124 125
125 126 def test_returns_http_client_when_protocol_matches(self):
126 127 hooks_uri = 'localhost:8000'
127 128 result = hooks._get_hooks_client({
128 129 'hooks_uri': hooks_uri,
129 130 'hooks_protocol': 'http'
130 131 })
131 132 assert isinstance(result, hooks.HooksHttpClient)
132 133 assert result.hooks_uri == hooks_uri
133 134
134 135 def test_returns_dummy_client_when_hooks_uri_not_specified(self):
135 136 fake_module = mock.Mock()
136 137 import_patcher = mock.patch.object(
137 138 hooks.importlib, 'import_module', return_value=fake_module)
138 139 fake_module_name = 'fake.module'
139 140 with import_patcher as import_mock:
140 141 result = hooks._get_hooks_client(
141 142 {'hooks_module': fake_module_name})
142 143
143 144 import_mock.assert_called_once_with(fake_module_name)
144 145 assert isinstance(result, hooks.HooksDummyClient)
145 146 assert result._hooks_module == fake_module
146 147
147 148
148 149 class TestHooksHttpClient(object):
149 150 def test_init_sets_hooks_uri(self):
150 151 uri = 'localhost:3000'
151 152 client = hooks.HooksHttpClient(uri)
152 153 assert client.hooks_uri == uri
153 154
154 155 def test_serialize_returns_serialized_string(self):
155 156 client = hooks.HooksHttpClient('localhost:3000')
156 157 hook_name = 'test'
157 158 extras = {
158 159 'first': 1,
159 160 'second': 'two'
160 161 }
161 162 hooks_proto, result = client._serialize(hook_name, extras)
162 163 expected_result = msgpack.packb({
163 164 'method': hook_name,
164 165 'extras': extras,
165 166 })
166 167 assert hooks_proto == {'rc-hooks-protocol': 'msgpack.v1'}
167 168 assert result == expected_result
168 169
169 170 def test_call_queries_http_server(self, http_mirror):
170 171 client = hooks.HooksHttpClient(http_mirror.uri)
171 172 hook_name = 'test'
172 173 extras = {
173 174 'first': 1,
174 175 'second': 'two'
175 176 }
176 177 result = client(hook_name, extras)
177 178 expected_result = msgpack.unpackb(msgpack.packb({
178 179 'method': hook_name,
179 180 'extras': extras
180 181 }), raw=False)
181 182 assert result == expected_result
182 183
183 184
184 185 class TestHooksDummyClient(object):
185 186 def test_init_imports_hooks_module(self):
186 187 hooks_module_name = 'rhodecode.fake.module'
187 188 hooks_module = mock.MagicMock()
188 189
189 190 import_patcher = mock.patch.object(
190 191 hooks.importlib, 'import_module', return_value=hooks_module)
191 192 with import_patcher as import_mock:
192 193 client = hooks.HooksDummyClient(hooks_module_name)
193 194 import_mock.assert_called_once_with(hooks_module_name)
194 195 assert client._hooks_module == hooks_module
195 196
196 197 def test_call_returns_hook_result(self):
197 198 hooks_module_name = 'rhodecode.fake.module'
198 199 hooks_module = mock.MagicMock()
199 200 import_patcher = mock.patch.object(
200 201 hooks.importlib, 'import_module', return_value=hooks_module)
201 202 with import_patcher:
202 203 client = hooks.HooksDummyClient(hooks_module_name)
203 204
204 205 result = client('post_push', {})
205 206 hooks_module.Hooks.assert_called_once_with()
206 207 assert result == hooks_module.Hooks().__enter__().post_push()
207 208
208 209
209 210 @pytest.fixture
210 211 def http_mirror(request):
211 212 server = MirrorHttpServer()
212 213 request.addfinalizer(server.stop)
213 214 return server
214 215
215 216
216 217 class MirrorHttpHandler(BaseHTTPRequestHandler):
217 218
218 219 def do_POST(self):
219 220 length = int(self.headers['Content-Length'])
220 221 body = self.rfile.read(length)
221 222 self.send_response(200)
222 223 self.end_headers()
223 224 self.wfile.write(body)
224 225
225 226
226 227 class MirrorHttpServer(object):
227 228 ip_address = '127.0.0.1'
228 229 port = 0
229 230
230 231 def __init__(self):
231 232 self._daemon = TCPServer((self.ip_address, 0), MirrorHttpHandler)
232 233 _, self.port = self._daemon.server_address
233 234 self._thread = threading.Thread(target=self._daemon.serve_forever)
234 235 self._thread.daemon = True
235 236 self._thread.start()
236 237
237 238 def stop(self):
238 239 self._daemon.shutdown()
239 240 self._thread.join()
240 241 self._daemon = None
241 242 self._thread = None
242 243
243 244 @property
244 245 def uri(self):
245 246 return '{}:{}'.format(self.ip_address, self.port)
247
248
249 def test_hooks_http_client_init():
250 hooks_uri = 'http://localhost:8000'
251 client = HooksHttpClient(hooks_uri)
252 assert client.hooks_uri == hooks_uri
253
254
255 def test_hooks_http_client_call():
256 hooks_uri = 'http://localhost:8000'
257
258 method = 'test_method'
259 extras = {'key': 'value'}
260
261 with \
262 mock.patch('vcsserver.hooks.HTTPConnection') as mock_connection,\
263 mock.patch('msgpack.load') as mock_load:
264
265 client = HooksHttpClient(hooks_uri)
266
267 mock_load.return_value = {'result': 'success'}
268 response = mock.MagicMock()
269 response.status = 200
270 mock_connection.request.side_effect = None
271 mock_connection.getresponse.return_value = response
272
273 result = client(method, extras)
274
275 mock_connection.assert_called_with(hooks_uri)
276 mock_connection.return_value.request.assert_called_once()
277 assert result == {'result': 'success'}
278
279
280 def test_hooks_http_client_serialize():
281 method = 'test_method'
282 extras = {'key': 'value'}
283 headers, body = HooksHttpClient._serialize(method, extras)
284
285 assert headers == {'rc-hooks-protocol': HooksHttpClient.proto}
286 assert msgpack.unpackb(body) == {'method': method, 'extras': extras}
General Comments 0
You need to be logged in to leave comments. Login now