##// END OF EJS Templates
tests: push with force in test_vcs_operations.py _add_files_and_push...
Mads Kiilerich -
r7660:76e2072b default
parent child Browse files
Show More
@@ -1,577 +1,577 b''
1 1 # -*- coding: utf-8 -*-
2 2 # This program is free software: you can redistribute it and/or modify
3 3 # it under the terms of the GNU General Public License as published by
4 4 # the Free Software Foundation, either version 3 of the License, or
5 5 # (at your option) any later version.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 """
15 15 Test suite for vcs push/pull operations.
16 16
17 17 The tests need Git > 1.8.1.
18 18
19 19 This file was forked by the Kallithea project in July 2014.
20 20 Original author and date, and relevant copyright and licensing information is below:
21 21 :created_on: Dec 30, 2010
22 22 :author: marcink
23 23 :copyright: (c) 2013 RhodeCode GmbH, and others.
24 24 :license: GPLv3, see LICENSE.md for more details.
25 25
26 26 """
27 27
28 28 import os
29 29 import re
30 30 import tempfile
31 31 import time
32 32 import urllib2
33 33 import json
34 34 from tempfile import _RandomNameSequence
35 35 from subprocess import Popen, PIPE
36 36
37 37 import pytest
38 38
39 39 from kallithea.tests.base import *
40 40 from kallithea.tests.fixture import Fixture
41 41 from kallithea.model.db import User, Repository, UserIpMap, CacheInvalidation, Ui, UserLog
42 42 from kallithea.model.meta import Session
43 43 from kallithea.model.repo import RepoModel
44 44 from kallithea.model.user import UserModel
45 45
46 46 DEBUG = True
47 47 HOST = '127.0.0.1:4999' # test host
48 48
49 49 fixture = Fixture()
50 50
51 51
52 52 # Parameterize different kinds of VCS testing - both the kind of VCS and the
53 53 # access method (HTTP/SSH)
54 54
55 55 # Mixin for using HTTP URLs
56 56 class HttpVcsTest(object):
57 57 @staticmethod
58 58 def repo_url_param(webserver, repo_name, **kwargs):
59 59 return webserver.repo_url(repo_name, **kwargs)
60 60
61 61 # Mixins for using Mercurial and Git
62 62 class HgVcsTest(object):
63 63 repo_type = 'hg'
64 64 repo_name = HG_REPO
65 65
66 66 class GitVcsTest(object):
67 67 repo_type = 'git'
68 68 repo_name = GIT_REPO
69 69
70 70 # Combine mixins to give the combinations we want to parameterize tests with
71 71 class HgHttpVcsTest(HgVcsTest, HttpVcsTest):
72 72 pass
73 73
74 74 class GitHttpVcsTest(GitVcsTest, HttpVcsTest):
75 75 pass
76 76
77 77 parametrize_vcs_test = parametrize('vt', [
78 78 HgHttpVcsTest,
79 79 GitHttpVcsTest,
80 80 ])
81 81 parametrize_vcs_test_hg = parametrize('vt', [
82 82 HgHttpVcsTest,
83 83 ])
84 84 parametrize_vcs_test_http = parametrize('vt', [
85 85 HgHttpVcsTest,
86 86 GitHttpVcsTest,
87 87 ])
88 88
89 89 class Command(object):
90 90
91 91 def __init__(self, cwd):
92 92 self.cwd = cwd
93 93
94 94 def execute(self, *args, **environ):
95 95 """
96 96 Runs command on the system with given ``args`` using simple space
97 97 join without safe quoting.
98 98 """
99 99 command = ' '.join(args)
100 100 ignoreReturnCode = environ.pop('ignoreReturnCode', False)
101 101 if DEBUG:
102 102 print '*** CMD %s ***' % command
103 103 testenv = dict(os.environ)
104 104 testenv['LANG'] = 'en_US.UTF-8'
105 105 testenv['LANGUAGE'] = 'en_US:en'
106 106 testenv['HGPLAIN'] = ''
107 107 testenv['HGRCPATH'] = ''
108 108 testenv.update(environ)
109 109 p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, cwd=self.cwd, env=testenv)
110 110 stdout, stderr = p.communicate()
111 111 if DEBUG:
112 112 if stdout:
113 113 print 'stdout:', stdout
114 114 if stderr:
115 115 print 'stderr:', stderr
116 116 if not ignoreReturnCode:
117 117 assert p.returncode == 0
118 118 return stdout, stderr
119 119
120 120
121 121 def _get_tmp_dir(prefix='vcs_operations-', suffix=''):
122 122 return tempfile.mkdtemp(dir=TESTS_TMP_PATH, prefix=prefix, suffix=suffix)
123 123
124 124
125 125 def _add_files(vcs, dest_dir, files_no=3):
126 126 """
127 127 Generate some files, add it to dest_dir repo and push back
128 128 vcs is git or hg and defines what VCS we want to make those files for
129 129
130 130 :param vcs:
131 131 :param dest_dir:
132 132 """
133 133 added_file = '%ssetup.py' % _RandomNameSequence().next()
134 134 open(os.path.join(dest_dir, added_file), 'a').close()
135 135 Command(dest_dir).execute(vcs, 'add', added_file)
136 136
137 137 email = 'me@example.com'
138 138 if os.name == 'nt':
139 139 author_str = 'User <%s>' % email
140 140 else:
141 141 author_str = 'User ǝɯɐᴎ <%s>' % email
142 142 for i in xrange(files_no):
143 143 cmd = """echo "added_line%s" >> %s""" % (i, added_file)
144 144 Command(dest_dir).execute(cmd)
145 145 if vcs == 'hg':
146 146 cmd = """hg commit -m "committed new %s" -u "%s" "%s" """ % (
147 147 i, author_str, added_file
148 148 )
149 149 elif vcs == 'git':
150 150 cmd = """git commit -m "committed new %s" --author "%s" "%s" """ % (
151 151 i, author_str, added_file
152 152 )
153 153 # git commit needs EMAIL on some machines
154 154 Command(dest_dir).execute(cmd, EMAIL=email)
155 155
156 156 def _add_files_and_push(webserver, vt, dest_dir, clone_url, ignoreReturnCode=False, files_no=3):
157 157 _add_files(vt.repo_type, dest_dir, files_no=files_no)
158 158 # PUSH it back
159 159 stdout = stderr = None
160 160 if vt.repo_type == 'hg':
161 stdout, stderr = Command(dest_dir).execute('hg push --verbose', clone_url, ignoreReturnCode=ignoreReturnCode)
161 stdout, stderr = Command(dest_dir).execute('hg push -f --verbose', clone_url, ignoreReturnCode=ignoreReturnCode)
162 162 elif vt.repo_type == 'git':
163 stdout, stderr = Command(dest_dir).execute('git push --verbose', clone_url, "master", ignoreReturnCode=ignoreReturnCode)
163 stdout, stderr = Command(dest_dir).execute('git push -f --verbose', clone_url, "master", ignoreReturnCode=ignoreReturnCode)
164 164
165 165 return stdout, stderr
166 166
167 167
168 168 def _check_outgoing(vcs, cwd, clone_url):
169 169 if vcs == 'hg':
170 170 # hg removes the password from default URLs, so we have to provide it here via the clone_url
171 171 return Command(cwd).execute('hg -q outgoing', clone_url, ignoreReturnCode=True)
172 172 elif vcs == 'git':
173 173 Command(cwd).execute('git remote update')
174 174 return Command(cwd).execute('git log origin/master..master')
175 175
176 176
177 177 def set_anonymous_access(enable=True):
178 178 user = User.get_default_user()
179 179 user.active = enable
180 180 Session().commit()
181 181 if enable != User.get_default_user().active:
182 182 raise Exception('Cannot set anonymous access')
183 183
184 184
185 185 #==============================================================================
186 186 # TESTS
187 187 #==============================================================================
188 188
189 189
190 190 def _check_proper_git_push(stdout, stderr):
191 191 assert 'fatal' not in stderr
192 192 assert 'rejected' not in stderr
193 193 assert 'Pushing to' in stderr
194 194 assert 'master -> master' in stderr
195 195
196 196
197 197 @pytest.mark.usefixtures("test_context_fixture")
198 198 class TestVCSOperations(TestController):
199 199
200 200 @classmethod
201 201 def setup_class(cls):
202 202 # DISABLE ANONYMOUS ACCESS
203 203 set_anonymous_access(False)
204 204
205 205 @pytest.fixture()
206 206 def testhook_cleanup(self):
207 207 yield
208 208 # remove hook
209 209 for hook in ['prechangegroup', 'pretxnchangegroup', 'preoutgoing', 'changegroup', 'outgoing', 'incoming']:
210 210 entry = Ui.get_by_key('hooks', '%s.testhook' % hook)
211 211 if entry:
212 212 Session().delete(entry)
213 213 Session().commit()
214 214
215 215 @pytest.fixture(scope="module")
216 216 def testfork(self):
217 217 # create fork so the repo stays untouched
218 218 git_fork_name = u'%s_fork%s' % (GIT_REPO, _RandomNameSequence().next())
219 219 fixture.create_fork(GIT_REPO, git_fork_name)
220 220 hg_fork_name = u'%s_fork%s' % (HG_REPO, _RandomNameSequence().next())
221 221 fixture.create_fork(HG_REPO, hg_fork_name)
222 222 return {'git': git_fork_name, 'hg': hg_fork_name}
223 223
224 224 @parametrize_vcs_test
225 225 def test_clone_repo_by_admin(self, webserver, vt):
226 226 clone_url = vt.repo_url_param(webserver, vt.repo_name)
227 227 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir())
228 228
229 229 if vt.repo_type == 'git':
230 230 assert 'Cloning into' in stdout + stderr
231 231 assert stderr == '' or stdout == ''
232 232 elif vt.repo_type == 'hg':
233 233 assert 'requesting all changes' in stdout
234 234 assert 'adding changesets' in stdout
235 235 assert 'adding manifests' in stdout
236 236 assert 'adding file changes' in stdout
237 237 assert stderr == ''
238 238
239 239 @parametrize_vcs_test_http
240 240 def test_clone_wrong_credentials(self, webserver, vt):
241 241 clone_url = vt.repo_url_param(webserver, vt.repo_name, password='bad!')
242 242 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
243 243 if vt.repo_type == 'git':
244 244 assert 'fatal: Authentication failed' in stderr
245 245 elif vt.repo_type == 'hg':
246 246 assert 'abort: authorization failed' in stderr
247 247
248 248 def test_clone_git_dir_as_hg(self, webserver):
249 249 clone_url = HgHttpVcsTest.repo_url_param(webserver, GIT_REPO)
250 250 stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
251 251 assert 'HTTP Error 404: Not Found' in stderr
252 252
253 253 def test_clone_hg_repo_as_git(self, webserver):
254 254 clone_url = GitHttpVcsTest.repo_url_param(webserver, HG_REPO)
255 255 stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
256 256 assert 'not found' in stderr
257 257
258 258 @parametrize_vcs_test
259 259 def test_clone_non_existing_path(self, webserver, vt):
260 260 clone_url = vt.repo_url_param(webserver, 'trololo')
261 261 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
262 262 if vt.repo_type == 'git':
263 263 assert 'not found' in stderr
264 264 elif vt.repo_type == 'hg':
265 265 assert 'HTTP Error 404: Not Found' in stderr
266 266
267 267 @parametrize_vcs_test
268 268 def test_push_new_repo(self, webserver, vt):
269 269 # Clear the log so we know what is added
270 270 UserLog.query().delete()
271 271 Session().commit()
272 272
273 273 # Create an empty server repo using the API
274 274 repo_name = u'new_%s_%s' % (vt.repo_type, _RandomNameSequence().next())
275 275 usr = User.get_by_username(TEST_USER_ADMIN_LOGIN)
276 276 params = {
277 277 "id": 7,
278 278 "api_key": usr.api_key,
279 279 "method": 'create_repo',
280 280 "args": dict(repo_name=repo_name,
281 281 owner=TEST_USER_ADMIN_LOGIN,
282 282 repo_type=vt.repo_type),
283 283 }
284 284 req = urllib2.Request(
285 285 'http://%s:%s/_admin/api' % webserver.server_address,
286 286 data=json.dumps(params),
287 287 headers={'content-type': 'application/json'})
288 288 response = urllib2.urlopen(req)
289 289 result = json.loads(response.read())
290 290 # Expect something like:
291 291 # {u'result': {u'msg': u'Created new repository `new_XXX`', u'task': None, u'success': True}, u'id': 7, u'error': None}
292 292 assert result[u'result'][u'success']
293 293
294 294 # Create local clone of the empty server repo
295 295 local_clone_dir = _get_tmp_dir()
296 296 clone_url = vt.repo_url_param(webserver, repo_name)
297 297 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, local_clone_dir)
298 298
299 299 # Make 3 commits and push to the empty server repo.
300 300 # The server repo doesn't have any other heads than the
301 301 # refs/heads/master we are pushing, but the `git log` in the push hook
302 302 # should still list the 3 commits.
303 303 stdout, stderr = _add_files_and_push(webserver, vt, local_clone_dir, clone_url=clone_url)
304 304 if vt.repo_type == 'git':
305 305 _check_proper_git_push(stdout, stderr)
306 306 elif vt.repo_type == 'hg':
307 307 assert 'pushing to ' in stdout
308 308 assert 'remote: added ' in stdout
309 309
310 310 # Verify that we got the right events in UserLog. Expect something like:
311 311 # <UserLog('id:new_git_XXX:started_following_repo')>
312 312 # <UserLog('id:new_git_XXX:user_created_repo')>
313 313 # <UserLog('id:new_git_XXX:pull')>
314 314 # <UserLog('id:new_git_XXX:push:aed9d4c1732a1927da3be42c47eb9afdc200d427,d38b083a07af10a9f44193486959a96a23db78da,4841ff9a2b385bec995f4679ef649adb3f437622')>
315 315 action_parts = [ul.action.split(':', 1) for ul in UserLog.query().order_by(UserLog.user_log_id)]
316 316 assert [(t[0], (t[1].count(',') + 1) if len(t) == 2 else 0) for t in action_parts] == ([
317 317 (u'started_following_repo', 0),
318 318 (u'user_created_repo', 0),
319 319 (u'pull', 0),
320 320 (u'push', 3)]
321 321 if vt.repo_type == 'git' else [
322 322 (u'started_following_repo', 0),
323 323 (u'user_created_repo', 0),
324 324 # (u'pull', 0), # Mercurial outgoing hook is not called for empty clones
325 325 (u'push', 3)])
326 326
327 327 @parametrize_vcs_test
328 328 def test_push_new_file(self, webserver, testfork, vt):
329 329 UserLog.query().delete()
330 330 Session().commit()
331 331
332 332 dest_dir = _get_tmp_dir()
333 333 clone_url = vt.repo_url_param(webserver, vt.repo_name)
334 334 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir)
335 335
336 336 clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type])
337 337 stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, clone_url=clone_url)
338 338
339 339 if vt.repo_type == 'git':
340 340 _check_proper_git_push(stdout, stderr)
341 341 elif vt.repo_type == 'hg':
342 342 assert 'pushing to' in stdout
343 343 assert 'Repository size' in stdout
344 344 assert 'Last revision is now' in stdout
345 345
346 346 action_parts = [ul.action.split(':', 1) for ul in UserLog.query().order_by(UserLog.user_log_id)]
347 347 assert [(t[0], (t[1].count(',') + 1) if len(t) == 2 else 0) for t in action_parts] == \
348 348 [(u'pull', 0), (u'push', 3)]
349 349
350 350 @parametrize_vcs_test
351 351 def test_pull(self, webserver, testfork, vt):
352 352 UserLog.query().delete()
353 353 Session().commit()
354 354
355 355 dest_dir = _get_tmp_dir()
356 356 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'init', dest_dir)
357 357
358 358 clone_url = vt.repo_url_param(webserver, vt.repo_name)
359 359 print (vt, clone_url)
360 360 stdout, stderr = Command(dest_dir).execute(vt.repo_type, 'pull', clone_url)
361 361
362 362 if vt.repo_type == 'git':
363 363 assert 'FETCH_HEAD' in stderr
364 364 elif vt.repo_type == 'hg':
365 365 assert 'new changesets' in stdout
366 366
367 367 action_parts = [ul.action for ul in UserLog.query().order_by(UserLog.user_log_id)]
368 368 assert action_parts == [u'pull']
369 369
370 370 @parametrize_vcs_test
371 371 def test_push_invalidates_cache(self, webserver, testfork, vt):
372 372 pre_cached_tip = [repo.get_api_data()['last_changeset']['short_id'] for repo in Repository.query().filter(Repository.repo_name == testfork[vt.repo_type])]
373 373
374 374 key = CacheInvalidation.query().filter(CacheInvalidation.cache_key
375 375 == testfork[vt.repo_type]).scalar()
376 376 if not key:
377 377 key = CacheInvalidation(testfork[vt.repo_type], testfork[vt.repo_type])
378 378 Session().add(key)
379 379
380 380 key.cache_active = True
381 381 Session().commit()
382 382
383 383 dest_dir = _get_tmp_dir()
384 384 clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type])
385 385 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir)
386 386
387 387 stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, files_no=1, clone_url=clone_url)
388 388
389 389 if vt.repo_type == 'git':
390 390 _check_proper_git_push(stdout, stderr)
391 391
392 392 post_cached_tip = [repo.get_api_data()['last_changeset']['short_id'] for repo in Repository.query().filter(Repository.repo_name == testfork[vt.repo_type])]
393 393 assert pre_cached_tip != post_cached_tip
394 394
395 395 key = CacheInvalidation.query().filter(CacheInvalidation.cache_key
396 396 == testfork[vt.repo_type]).all()
397 397 assert key == []
398 398
399 399 @parametrize_vcs_test_http
400 400 def test_push_wrong_credentials(self, webserver, vt):
401 401 dest_dir = _get_tmp_dir()
402 402 clone_url = vt.repo_url_param(webserver, vt.repo_name)
403 403 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir)
404 404
405 405 clone_url = webserver.repo_url(vt.repo_name, username='bad', password='name')
406 406 stdout, stderr = _add_files_and_push(webserver, vt, dest_dir,
407 407 clone_url=clone_url, ignoreReturnCode=True)
408 408
409 409 if vt.repo_type == 'git':
410 410 assert 'fatal: Authentication failed' in stderr
411 411 elif vt.repo_type == 'hg':
412 412 assert 'abort: authorization failed' in stderr
413 413
414 414 @parametrize_vcs_test
415 415 def test_push_with_readonly_credentials(self, webserver, vt):
416 416 UserLog.query().delete()
417 417 Session().commit()
418 418
419 419 dest_dir = _get_tmp_dir()
420 420 clone_url = vt.repo_url_param(webserver, vt.repo_name, username=TEST_USER_REGULAR_LOGIN, password=TEST_USER_REGULAR_PASS)
421 421 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir)
422 422
423 423 stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, ignoreReturnCode=True, clone_url=clone_url)
424 424
425 425 if vt.repo_type == 'git':
426 426 assert 'The requested URL returned error: 403' in stderr
427 427 elif vt.repo_type == 'hg':
428 428 assert 'abort: HTTP Error 403: Forbidden' in stderr
429 429
430 430 action_parts = [ul.action.split(':', 1) for ul in UserLog.query().order_by(UserLog.user_log_id)]
431 431 assert [(t[0], (t[1].count(',') + 1) if len(t) == 2 else 0) for t in action_parts] == \
432 432 [(u'pull', 0)]
433 433
434 434 @parametrize_vcs_test
435 435 def test_push_back_to_wrong_url(self, webserver, vt):
436 436 dest_dir = _get_tmp_dir()
437 437 clone_url = vt.repo_url_param(webserver, vt.repo_name)
438 438 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir)
439 439
440 440 stdout, stderr = _add_files_and_push(
441 441 webserver, vt, dest_dir, clone_url='http://%s:%s/tmp' % (
442 442 webserver.server_address[0], webserver.server_address[1]),
443 443 ignoreReturnCode=True)
444 444
445 445 if vt.repo_type == 'git':
446 446 assert 'not found' in stderr
447 447 elif vt.repo_type == 'hg':
448 448 assert 'HTTP Error 404: Not Found' in stderr
449 449
450 450 @parametrize_vcs_test
451 451 def test_ip_restriction(self, webserver, vt):
452 452 user_model = UserModel()
453 453 try:
454 454 # Add IP constraint that excludes the test context:
455 455 user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32')
456 456 Session().commit()
457 457 # IP permissions are cached, need to wait for the cache in the server process to expire
458 458 time.sleep(1.5)
459 459 clone_url = vt.repo_url_param(webserver, vt.repo_name)
460 460 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
461 461 if vt.repo_type == 'git':
462 462 # The message apparently changed in Git 1.8.3, so match it loosely.
463 463 assert re.search(r'\b403\b', stderr)
464 464 elif vt.repo_type == 'hg':
465 465 assert 'abort: HTTP Error 403: Forbidden' in stderr
466 466 finally:
467 467 # release IP restrictions
468 468 for ip in UserIpMap.query():
469 469 UserIpMap.delete(ip.ip_id)
470 470 Session().commit()
471 471 # IP permissions are cached, need to wait for the cache in the server process to expire
472 472 time.sleep(1.5)
473 473
474 474 clone_url = vt.repo_url_param(webserver, vt.repo_name)
475 475 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir())
476 476
477 477 if vt.repo_type == 'git':
478 478 assert 'Cloning into' in stdout + stderr
479 479 assert stderr == '' or stdout == ''
480 480 elif vt.repo_type == 'hg':
481 481 assert 'requesting all changes' in stdout
482 482 assert 'adding changesets' in stdout
483 483 assert 'adding manifests' in stdout
484 484 assert 'adding file changes' in stdout
485 485
486 486 assert stderr == ''
487 487
488 488 @parametrize_vcs_test_hg # git hooks doesn't work like hg hooks
489 489 def test_custom_hooks_preoutgoing(self, testhook_cleanup, webserver, testfork, vt):
490 490 # set prechangegroup to failing hook (returns True)
491 491 Ui.create_or_update_hook('preoutgoing.testhook', 'python:kallithea.tests.fixture.failing_test_hook')
492 492 Session().commit()
493 493 # clone repo
494 494 clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type], username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS)
495 495 dest_dir = _get_tmp_dir()
496 496 stdout, stderr = Command(TESTS_TMP_PATH) \
497 497 .execute(vt.repo_type, 'clone', clone_url, dest_dir, ignoreReturnCode=True)
498 498 if vt.repo_type == 'hg':
499 499 assert 'preoutgoing.testhook hook failed' in stdout
500 500 elif vt.repo_type == 'git':
501 501 assert 'error: 406' in stderr
502 502
503 503 @parametrize_vcs_test_hg # git hooks doesn't work like hg hooks
504 504 def test_custom_hooks_prechangegroup(self, testhook_cleanup, webserver, testfork, vt):
505 505 # set prechangegroup to failing hook (returns exit code 1)
506 506 Ui.create_or_update_hook('prechangegroup.testhook', 'python:kallithea.tests.fixture.failing_test_hook')
507 507 Session().commit()
508 508 # clone repo
509 509 clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type], username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS)
510 510 dest_dir = _get_tmp_dir()
511 511 stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir)
512 512
513 513 stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, clone_url,
514 514 ignoreReturnCode=True)
515 515 assert 'failing_test_hook failed' in stdout + stderr
516 516 assert 'Traceback' not in stdout + stderr
517 517 assert 'prechangegroup.testhook hook failed' in stdout + stderr
518 518 # there are still outgoing changesets
519 519 stdout, stderr = _check_outgoing(vt.repo_type, dest_dir, clone_url)
520 520 assert stdout != ''
521 521
522 522 # set prechangegroup hook to exception throwing method
523 523 Ui.create_or_update_hook('prechangegroup.testhook', 'python:kallithea.tests.fixture.exception_test_hook')
524 524 Session().commit()
525 525 # re-try to push
526 526 stdout, stderr = Command(dest_dir).execute('%s push' % vt.repo_type, clone_url, ignoreReturnCode=True)
527 527 if vt is HgHttpVcsTest:
528 528 # like with 'hg serve...' 'HTTP Error 500: INTERNAL SERVER ERROR' should be returned
529 529 assert 'HTTP Error 500: INTERNAL SERVER ERROR' in stderr
530 530 else: assert False
531 531 # there are still outgoing changesets
532 532 stdout, stderr = _check_outgoing(vt.repo_type, dest_dir, clone_url)
533 533 assert stdout != ''
534 534
535 535 # set prechangegroup hook to method that returns False
536 536 Ui.create_or_update_hook('prechangegroup.testhook', 'python:kallithea.tests.fixture.passing_test_hook')
537 537 Session().commit()
538 538 # re-try to push
539 539 stdout, stderr = Command(dest_dir).execute('%s push' % vt.repo_type, clone_url, ignoreReturnCode=True)
540 540 assert 'passing_test_hook succeeded' in stdout + stderr
541 541 assert 'Traceback' not in stdout + stderr
542 542 assert 'prechangegroup.testhook hook failed' not in stdout + stderr
543 543 # no more outgoing changesets
544 544 stdout, stderr = _check_outgoing(vt.repo_type, dest_dir, clone_url)
545 545 assert stdout == ''
546 546 assert stderr == ''
547 547
548 548 def test_add_submodule_git(self, webserver, testfork):
549 549 dest_dir = _get_tmp_dir()
550 550 clone_url = GitHttpVcsTest.repo_url_param(webserver, GIT_REPO)
551 551
552 552 fork_url = GitHttpVcsTest.repo_url_param(webserver, testfork['git'])
553 553
554 554 # add submodule
555 555 stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', fork_url, dest_dir)
556 556 stdout, stderr = Command(dest_dir).execute('git submodule add', clone_url, 'testsubmodule')
557 557 stdout, stderr = Command(dest_dir).execute('git commit -am "added testsubmodule pointing to', clone_url, '"', EMAIL=TEST_USER_ADMIN_EMAIL)
558 558 stdout, stderr = Command(dest_dir).execute('git push', fork_url, 'master')
559 559
560 560 # check for testsubmodule link in files page
561 561 self.log_user()
562 562 response = self.app.get(url(controller='files', action='index',
563 563 repo_name=testfork['git'],
564 564 revision='tip',
565 565 f_path='/'))
566 566 # check _repo_files_url that will be used to reload as AJAX
567 567 response.mustcontain('var _repo_files_url = ("/%s/files/");' % testfork['git'])
568 568
569 569 response.mustcontain('<a class="submodule-dir" href="%s" target="_blank"><i class="icon-file-submodule"></i><span>testsubmodule @ ' % clone_url)
570 570
571 571 # check that following a submodule link actually works - and redirects
572 572 response = self.app.get(url(controller='files', action='index',
573 573 repo_name=testfork['git'],
574 574 revision='tip',
575 575 f_path='/testsubmodule'),
576 576 status=302)
577 577 assert response.location == clone_url
General Comments 0
You need to be logged in to leave comments. Login now