##// END OF EJS Templates
tests: avoid executing tests in base classes...
Marc Abramowitz -
r5051:12ae08b2 default
parent child Browse files
Show More
@@ -1,2295 +1,2295 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 """
16 16 tests for api. run with::
17 17
18 18 KALLITHEA_WHOOSH_TEST_DISABLE=1 nosetests --with-coverage --cover-package=kallithea.controllers.api.api -x kallithea/tests/api
19 19 """
20 20
21 21 from __future__ import with_statement
22 22 import os
23 23 import random
24 24 import mock
25 25
26 26 from kallithea.tests import *
27 27 from kallithea.tests.fixture import Fixture
28 28 from kallithea.lib.compat import json
29 29 from kallithea.lib.auth import AuthUser
30 30 from kallithea.model.user import UserModel
31 31 from kallithea.model.user_group import UserGroupModel
32 32 from kallithea.model.repo import RepoModel
33 33 from kallithea.model.repo_group import RepoGroupModel
34 34 from kallithea.model.meta import Session
35 35 from kallithea.model.scm import ScmModel
36 36 from kallithea.model.gist import GistModel
37 37 from kallithea.model.db import Repository, User, Setting
38 38 from kallithea.lib.utils2 import time_to_datetime
39 39
40 40
41 41 API_URL = '/_admin/api'
42 42 TEST_USER_GROUP = 'test_user_group'
43 43 TEST_REPO_GROUP = 'test_repo_group'
44 44
45 45 fixture = Fixture()
46 46
47 47
48 48 def _build_data(apikey, method, **kw):
49 49 """
50 50 Builds API data with given random ID
51 51
52 52 :param random_id:
53 53 """
54 54 random_id = random.randrange(1, 9999)
55 55 return random_id, json.dumps({
56 56 "id": random_id,
57 57 "api_key": apikey,
58 58 "method": method,
59 59 "args": kw
60 60 })
61 61
62 62
63 63 jsonify = lambda obj: json.loads(json.dumps(obj))
64 64
65 65
66 66 def crash(*args, **kwargs):
67 67 raise Exception('Total Crash !')
68 68
69 69
70 70 def api_call(test_obj, params):
71 71 response = test_obj.app.post(API_URL, content_type='application/json',
72 72 params=params)
73 73 return response
74 74
75 75
76 76 ## helpers
77 77 def make_user_group(name=TEST_USER_GROUP):
78 78 gr = fixture.create_user_group(name, cur_user=TEST_USER_ADMIN_LOGIN)
79 79 UserGroupModel().add_user_to_group(user_group=gr,
80 80 user=TEST_USER_ADMIN_LOGIN)
81 81 Session().commit()
82 82 return gr
83 83
84 84
85 85 def make_repo_group(name=TEST_REPO_GROUP):
86 86 gr = fixture.create_repo_group(name, cur_user=TEST_USER_ADMIN_LOGIN)
87 87 Session().commit()
88 88 return gr
89 89
90 90
91 class BaseTestApi(object):
91 class _BaseTestApi(object):
92 92 REPO = None
93 93 REPO_TYPE = None
94 94
95 95 @classmethod
96 96 def setup_class(cls):
97 97 cls.usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
98 98 cls.apikey = cls.usr.api_key
99 99 cls.test_user = UserModel().create_or_update(
100 100 username='test-api',
101 101 password='test',
102 102 email='test@example.com',
103 103 firstname='first',
104 104 lastname='last'
105 105 )
106 106 Session().commit()
107 107 cls.TEST_USER_LOGIN = cls.test_user.username
108 108 cls.apikey_regular = cls.test_user.api_key
109 109
110 110 @classmethod
111 111 def teardown_class(cls):
112 112 pass
113 113
114 114 def setUp(self):
115 115 self.maxDiff = None
116 116 make_user_group()
117 117 make_repo_group()
118 118
119 119 def tearDown(self):
120 120 fixture.destroy_user_group(TEST_USER_GROUP)
121 121 fixture.destroy_gists()
122 122 fixture.destroy_repo_group(TEST_REPO_GROUP)
123 123
124 124 def _compare_ok(self, id_, expected, given):
125 125 expected = jsonify({
126 126 'id': id_,
127 127 'error': None,
128 128 'result': expected
129 129 })
130 130 given = json.loads(given)
131 131 self.assertEqual(expected, given)
132 132
133 133 def _compare_error(self, id_, expected, given):
134 134 expected = jsonify({
135 135 'id': id_,
136 136 'error': expected,
137 137 'result': None
138 138 })
139 139 given = json.loads(given)
140 140 self.assertEqual(expected, given)
141 141
142 142 def test_Optional_object(self):
143 143 from kallithea.controllers.api.api import Optional
144 144
145 145 option1 = Optional(None)
146 146 self.assertEqual('<Optional:%s>' % None, repr(option1))
147 147 self.assertEqual(option1(), None)
148 148
149 149 self.assertEqual(1, Optional.extract(Optional(1)))
150 150 self.assertEqual('trololo', Optional.extract('trololo'))
151 151
152 152 def test_Optional_OAttr(self):
153 153 from kallithea.controllers.api.api import Optional, OAttr
154 154
155 155 option1 = Optional(OAttr('apiuser'))
156 156 self.assertEqual('apiuser', Optional.extract(option1))
157 157
158 158 def test_OAttr_object(self):
159 159 from kallithea.controllers.api.api import OAttr
160 160
161 161 oattr1 = OAttr('apiuser')
162 162 self.assertEqual('<OptionalAttr:apiuser>', repr(oattr1))
163 163 self.assertEqual(oattr1(), oattr1)
164 164
165 165 def test_api_wrong_key(self):
166 166 id_, params = _build_data('trololo', 'get_user')
167 167 response = api_call(self, params)
168 168
169 169 expected = 'Invalid API KEY'
170 170 self._compare_error(id_, expected, given=response.body)
171 171
172 172 def test_api_missing_non_optional_param(self):
173 173 id_, params = _build_data(self.apikey, 'get_repo')
174 174 response = api_call(self, params)
175 175
176 176 expected = 'Missing non optional `repoid` arg in JSON DATA'
177 177 self._compare_error(id_, expected, given=response.body)
178 178
179 179 def test_api_missing_non_optional_param_args_null(self):
180 180 id_, params = _build_data(self.apikey, 'get_repo')
181 181 params = params.replace('"args": {}', '"args": null')
182 182 response = api_call(self, params)
183 183
184 184 expected = 'Missing non optional `repoid` arg in JSON DATA'
185 185 self._compare_error(id_, expected, given=response.body)
186 186
187 187 def test_api_missing_non_optional_param_args_bad(self):
188 188 id_, params = _build_data(self.apikey, 'get_repo')
189 189 params = params.replace('"args": {}', '"args": 1')
190 190 response = api_call(self, params)
191 191
192 192 expected = 'Missing non optional `repoid` arg in JSON DATA'
193 193 self._compare_error(id_, expected, given=response.body)
194 194
195 195 def test_api_args_is_null(self):
196 196 id_, params = _build_data(self.apikey, 'get_users', )
197 197 params = params.replace('"args": {}', '"args": null')
198 198 response = api_call(self, params)
199 199 self.assertEqual(response.status, '200 OK')
200 200
201 201 def test_api_args_is_bad(self):
202 202 id_, params = _build_data(self.apikey, 'get_users', )
203 203 params = params.replace('"args": {}', '"args": 1')
204 204 response = api_call(self, params)
205 205 self.assertEqual(response.status, '200 OK')
206 206
207 207 def test_api_args_different_args(self):
208 208 import string
209 209 expected = {
210 210 'ascii_letters': string.ascii_letters,
211 211 'ws': string.whitespace,
212 212 'printables': string.printable
213 213 }
214 214 id_, params = _build_data(self.apikey, 'test', args=expected)
215 215 response = api_call(self, params)
216 216 self.assertEqual(response.status, '200 OK')
217 217 self._compare_ok(id_, expected, response.body)
218 218
219 219 def test_api_get_users(self):
220 220 id_, params = _build_data(self.apikey, 'get_users', )
221 221 response = api_call(self, params)
222 222 ret_all = []
223 223 _users = User.query().filter(User.username != User.DEFAULT_USER) \
224 224 .order_by(User.username).all()
225 225 for usr in _users:
226 226 ret = usr.get_api_data()
227 227 ret_all.append(jsonify(ret))
228 228 expected = ret_all
229 229 self._compare_ok(id_, expected, given=response.body)
230 230
231 231 def test_api_get_user(self):
232 232 id_, params = _build_data(self.apikey, 'get_user',
233 233 userid=TEST_USER_ADMIN_LOGIN)
234 234 response = api_call(self, params)
235 235
236 236 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
237 237 ret = usr.get_api_data()
238 238 ret['permissions'] = AuthUser(usr.user_id).permissions
239 239
240 240 expected = ret
241 241 self._compare_ok(id_, expected, given=response.body)
242 242
243 243 def test_api_get_user_that_does_not_exist(self):
244 244 id_, params = _build_data(self.apikey, 'get_user',
245 245 userid='trololo')
246 246 response = api_call(self, params)
247 247
248 248 expected = "user `%s` does not exist" % 'trololo'
249 249 self._compare_error(id_, expected, given=response.body)
250 250
251 251 def test_api_get_user_without_giving_userid(self):
252 252 id_, params = _build_data(self.apikey, 'get_user')
253 253 response = api_call(self, params)
254 254
255 255 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
256 256 ret = usr.get_api_data()
257 257 ret['permissions'] = AuthUser(usr.user_id).permissions
258 258
259 259 expected = ret
260 260 self._compare_ok(id_, expected, given=response.body)
261 261
262 262 def test_api_get_user_without_giving_userid_non_admin(self):
263 263 id_, params = _build_data(self.apikey_regular, 'get_user')
264 264 response = api_call(self, params)
265 265
266 266 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
267 267 ret = usr.get_api_data()
268 268 ret['permissions'] = AuthUser(usr.user_id).permissions
269 269
270 270 expected = ret
271 271 self._compare_ok(id_, expected, given=response.body)
272 272
273 273 def test_api_get_user_with_giving_userid_non_admin(self):
274 274 id_, params = _build_data(self.apikey_regular, 'get_user',
275 275 userid=self.TEST_USER_LOGIN)
276 276 response = api_call(self, params)
277 277
278 278 expected = 'userid is not the same as your user'
279 279 self._compare_error(id_, expected, given=response.body)
280 280
281 281 def test_api_pull(self):
282 282 repo_name = 'test_pull'
283 283 r = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
284 284 r.clone_uri = os.path.join(TESTS_TMP_PATH, self.REPO)
285 285 Session.add(r)
286 286 Session.commit()
287 287
288 288 id_, params = _build_data(self.apikey, 'pull',
289 289 repoid=repo_name,)
290 290 response = api_call(self, params)
291 291
292 292 expected = {'msg': 'Pulled from `%s`' % repo_name,
293 293 'repository': repo_name}
294 294 self._compare_ok(id_, expected, given=response.body)
295 295
296 296 fixture.destroy_repo(repo_name)
297 297
298 298 def test_api_pull_error(self):
299 299 id_, params = _build_data(self.apikey, 'pull',
300 300 repoid=self.REPO, )
301 301 response = api_call(self, params)
302 302
303 303 expected = 'Unable to pull changes from `%s`' % self.REPO
304 304 self._compare_error(id_, expected, given=response.body)
305 305
306 306 def test_api_rescan_repos(self):
307 307 id_, params = _build_data(self.apikey, 'rescan_repos')
308 308 response = api_call(self, params)
309 309
310 310 expected = {'added': [], 'removed': []}
311 311 self._compare_ok(id_, expected, given=response.body)
312 312
313 313 @mock.patch.object(ScmModel, 'repo_scan', crash)
314 314 def test_api_rescann_error(self):
315 315 id_, params = _build_data(self.apikey, 'rescan_repos', )
316 316 response = api_call(self, params)
317 317
318 318 expected = 'Error occurred during rescan repositories action'
319 319 self._compare_error(id_, expected, given=response.body)
320 320
321 321 def test_api_invalidate_cache(self):
322 322 repo = RepoModel().get_by_repo_name(self.REPO)
323 323 repo.scm_instance_cached() # seed cache
324 324
325 325 id_, params = _build_data(self.apikey, 'invalidate_cache',
326 326 repoid=self.REPO)
327 327 response = api_call(self, params)
328 328
329 329 expected = {
330 330 'msg': "Cache for repository `%s` was invalidated" % (self.REPO,),
331 331 'repository': self.REPO
332 332 }
333 333 self._compare_ok(id_, expected, given=response.body)
334 334
335 335 @mock.patch.object(ScmModel, 'mark_for_invalidation', crash)
336 336 def test_api_invalidate_cache_error(self):
337 337 id_, params = _build_data(self.apikey, 'invalidate_cache',
338 338 repoid=self.REPO)
339 339 response = api_call(self, params)
340 340
341 341 expected = 'Error occurred during cache invalidation action'
342 342 self._compare_error(id_, expected, given=response.body)
343 343
344 344 def test_api_invalidate_cache_regular_user_no_permission(self):
345 345 repo = RepoModel().get_by_repo_name(self.REPO)
346 346 repo.scm_instance_cached() # seed cache
347 347
348 348 id_, params = _build_data(self.apikey_regular, 'invalidate_cache',
349 349 repoid=self.REPO)
350 350 response = api_call(self, params)
351 351
352 352 expected = "repository `%s` does not exist" % (self.REPO,)
353 353 self._compare_error(id_, expected, given=response.body)
354 354
355 355 def test_api_lock_repo_lock_aquire(self):
356 356 id_, params = _build_data(self.apikey, 'lock',
357 357 userid=TEST_USER_ADMIN_LOGIN,
358 358 repoid=self.REPO,
359 359 locked=True)
360 360 response = api_call(self, params)
361 361 expected = {
362 362 'repo': self.REPO, 'locked': True,
363 363 'locked_since': response.json['result']['locked_since'],
364 364 'locked_by': TEST_USER_ADMIN_LOGIN,
365 365 'lock_state_changed': True,
366 366 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
367 367 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
368 368 }
369 369 self._compare_ok(id_, expected, given=response.body)
370 370
371 371 def test_api_lock_repo_lock_aquire_by_non_admin(self):
372 372 repo_name = 'api_delete_me'
373 373 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
374 374 cur_user=self.TEST_USER_LOGIN)
375 375 try:
376 376 id_, params = _build_data(self.apikey_regular, 'lock',
377 377 repoid=repo_name,
378 378 locked=True)
379 379 response = api_call(self, params)
380 380 expected = {
381 381 'repo': repo_name,
382 382 'locked': True,
383 383 'locked_since': response.json['result']['locked_since'],
384 384 'locked_by': self.TEST_USER_LOGIN,
385 385 'lock_state_changed': True,
386 386 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
387 387 % (self.TEST_USER_LOGIN, repo_name, True))
388 388 }
389 389 self._compare_ok(id_, expected, given=response.body)
390 390 finally:
391 391 fixture.destroy_repo(repo_name)
392 392
393 393 def test_api_lock_repo_lock_aquire_non_admin_with_userid(self):
394 394 repo_name = 'api_delete_me'
395 395 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
396 396 cur_user=self.TEST_USER_LOGIN)
397 397 try:
398 398 id_, params = _build_data(self.apikey_regular, 'lock',
399 399 userid=TEST_USER_ADMIN_LOGIN,
400 400 repoid=repo_name,
401 401 locked=True)
402 402 response = api_call(self, params)
403 403 expected = 'userid is not the same as your user'
404 404 self._compare_error(id_, expected, given=response.body)
405 405 finally:
406 406 fixture.destroy_repo(repo_name)
407 407
408 408 def test_api_lock_repo_lock_aquire_non_admin_not_his_repo(self):
409 409 id_, params = _build_data(self.apikey_regular, 'lock',
410 410 repoid=self.REPO,
411 411 locked=True)
412 412 response = api_call(self, params)
413 413 expected = 'repository `%s` does not exist' % (self.REPO)
414 414 self._compare_error(id_, expected, given=response.body)
415 415
416 416 def test_api_lock_repo_lock_release(self):
417 417 id_, params = _build_data(self.apikey, 'lock',
418 418 userid=TEST_USER_ADMIN_LOGIN,
419 419 repoid=self.REPO,
420 420 locked=False)
421 421 response = api_call(self, params)
422 422 expected = {
423 423 'repo': self.REPO,
424 424 'locked': False,
425 425 'locked_since': None,
426 426 'locked_by': TEST_USER_ADMIN_LOGIN,
427 427 'lock_state_changed': True,
428 428 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
429 429 % (TEST_USER_ADMIN_LOGIN, self.REPO, False))
430 430 }
431 431 self._compare_ok(id_, expected, given=response.body)
432 432
433 433 def test_api_lock_repo_lock_aquire_optional_userid(self):
434 434 id_, params = _build_data(self.apikey, 'lock',
435 435 repoid=self.REPO,
436 436 locked=True)
437 437 response = api_call(self, params)
438 438 time_ = response.json['result']['locked_since']
439 439 expected = {
440 440 'repo': self.REPO,
441 441 'locked': True,
442 442 'locked_since': time_,
443 443 'locked_by': TEST_USER_ADMIN_LOGIN,
444 444 'lock_state_changed': True,
445 445 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
446 446 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
447 447 }
448 448
449 449 self._compare_ok(id_, expected, given=response.body)
450 450
451 451 def test_api_lock_repo_lock_optional_locked(self):
452 452 id_, params = _build_data(self.apikey, 'lock',
453 453 repoid=self.REPO)
454 454 response = api_call(self, params)
455 455 time_ = response.json['result']['locked_since']
456 456 expected = {
457 457 'repo': self.REPO,
458 458 'locked': True,
459 459 'locked_since': time_,
460 460 'locked_by': TEST_USER_ADMIN_LOGIN,
461 461 'lock_state_changed': False,
462 462 'msg': ('Repo `%s` locked by `%s` on `%s`.'
463 463 % (self.REPO, TEST_USER_ADMIN_LOGIN,
464 464 json.dumps(time_to_datetime(time_))))
465 465 }
466 466 self._compare_ok(id_, expected, given=response.body)
467 467
468 468 def test_api_lock_repo_lock_optional_not_locked(self):
469 469 repo_name = 'api_not_locked'
470 470 repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
471 471 cur_user=self.TEST_USER_LOGIN)
472 472 self.assertEqual(repo.locked, [None, None])
473 473 try:
474 474 id_, params = _build_data(self.apikey, 'lock',
475 475 repoid=repo.repo_id)
476 476 response = api_call(self, params)
477 477 expected = {
478 478 'repo': repo_name,
479 479 'locked': False,
480 480 'locked_since': None,
481 481 'locked_by': None,
482 482 'lock_state_changed': False,
483 483 'msg': ('Repo `%s` not locked.' % (repo_name,))
484 484 }
485 485 self._compare_ok(id_, expected, given=response.body)
486 486 finally:
487 487 fixture.destroy_repo(repo_name)
488 488
489 489 @mock.patch.object(Repository, 'lock', crash)
490 490 def test_api_lock_error(self):
491 491 id_, params = _build_data(self.apikey, 'lock',
492 492 userid=TEST_USER_ADMIN_LOGIN,
493 493 repoid=self.REPO,
494 494 locked=True)
495 495 response = api_call(self, params)
496 496
497 497 expected = 'Error occurred locking repository `%s`' % self.REPO
498 498 self._compare_error(id_, expected, given=response.body)
499 499
500 500 def test_api_get_locks_regular_user(self):
501 501 id_, params = _build_data(self.apikey_regular, 'get_locks')
502 502 response = api_call(self, params)
503 503 expected = []
504 504 self._compare_ok(id_, expected, given=response.body)
505 505
506 506 def test_api_get_locks_with_userid_regular_user(self):
507 507 id_, params = _build_data(self.apikey_regular, 'get_locks',
508 508 userid=TEST_USER_ADMIN_LOGIN)
509 509 response = api_call(self, params)
510 510 expected = 'userid is not the same as your user'
511 511 self._compare_error(id_, expected, given=response.body)
512 512
513 513 def test_api_get_locks(self):
514 514 id_, params = _build_data(self.apikey, 'get_locks')
515 515 response = api_call(self, params)
516 516 expected = []
517 517 self._compare_ok(id_, expected, given=response.body)
518 518
519 519 def test_api_get_locks_with_one_locked_repo(self):
520 520 repo_name = 'api_delete_me'
521 521 repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
522 522 cur_user=self.TEST_USER_LOGIN)
523 523 Repository.lock(repo, User.get_by_username(self.TEST_USER_LOGIN).user_id)
524 524 try:
525 525 id_, params = _build_data(self.apikey, 'get_locks')
526 526 response = api_call(self, params)
527 527 expected = [repo.get_api_data()]
528 528 self._compare_ok(id_, expected, given=response.body)
529 529 finally:
530 530 fixture.destroy_repo(repo_name)
531 531
532 532 def test_api_get_locks_with_one_locked_repo_for_specific_user(self):
533 533 repo_name = 'api_delete_me'
534 534 repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
535 535 cur_user=self.TEST_USER_LOGIN)
536 536 Repository.lock(repo, User.get_by_username(self.TEST_USER_LOGIN).user_id)
537 537 try:
538 538 id_, params = _build_data(self.apikey, 'get_locks',
539 539 userid=self.TEST_USER_LOGIN)
540 540 response = api_call(self, params)
541 541 expected = [repo.get_api_data()]
542 542 self._compare_ok(id_, expected, given=response.body)
543 543 finally:
544 544 fixture.destroy_repo(repo_name)
545 545
546 546 def test_api_get_locks_with_userid(self):
547 547 id_, params = _build_data(self.apikey, 'get_locks',
548 548 userid=TEST_USER_REGULAR_LOGIN)
549 549 response = api_call(self, params)
550 550 expected = []
551 551 self._compare_ok(id_, expected, given=response.body)
552 552
553 553 def test_api_create_existing_user(self):
554 554 id_, params = _build_data(self.apikey, 'create_user',
555 555 username=TEST_USER_ADMIN_LOGIN,
556 556 email='test@foo.com',
557 557 password='trololo')
558 558 response = api_call(self, params)
559 559
560 560 expected = "user `%s` already exist" % TEST_USER_ADMIN_LOGIN
561 561 self._compare_error(id_, expected, given=response.body)
562 562
563 563 def test_api_create_user_with_existing_email(self):
564 564 id_, params = _build_data(self.apikey, 'create_user',
565 565 username=TEST_USER_ADMIN_LOGIN + 'new',
566 566 email=TEST_USER_REGULAR_EMAIL,
567 567 password='trololo')
568 568 response = api_call(self, params)
569 569
570 570 expected = "email `%s` already exist" % TEST_USER_REGULAR_EMAIL
571 571 self._compare_error(id_, expected, given=response.body)
572 572
573 573 def test_api_create_user(self):
574 574 username = 'test_new_api_user'
575 575 email = username + "@foo.com"
576 576
577 577 id_, params = _build_data(self.apikey, 'create_user',
578 578 username=username,
579 579 email=email,
580 580 password='trololo')
581 581 response = api_call(self, params)
582 582
583 583 usr = UserModel().get_by_username(username)
584 584 ret = dict(
585 585 msg='created new user `%s`' % username,
586 586 user=jsonify(usr.get_api_data())
587 587 )
588 588
589 589 try:
590 590 expected = ret
591 591 self._compare_ok(id_, expected, given=response.body)
592 592 finally:
593 593 fixture.destroy_user(usr.user_id)
594 594
595 595 def test_api_create_user_without_password(self):
596 596 username = 'test_new_api_user_passwordless'
597 597 email = username + "@foo.com"
598 598
599 599 id_, params = _build_data(self.apikey, 'create_user',
600 600 username=username,
601 601 email=email)
602 602 response = api_call(self, params)
603 603
604 604 usr = UserModel().get_by_username(username)
605 605 ret = dict(
606 606 msg='created new user `%s`' % username,
607 607 user=jsonify(usr.get_api_data())
608 608 )
609 609 try:
610 610 expected = ret
611 611 self._compare_ok(id_, expected, given=response.body)
612 612 finally:
613 613 fixture.destroy_user(usr.user_id)
614 614
615 615 def test_api_create_user_with_extern_name(self):
616 616 username = 'test_new_api_user_passwordless'
617 617 email = username + "@foo.com"
618 618
619 619 id_, params = _build_data(self.apikey, 'create_user',
620 620 username=username,
621 621 email=email, extern_name='internal')
622 622 response = api_call(self, params)
623 623
624 624 usr = UserModel().get_by_username(username)
625 625 ret = dict(
626 626 msg='created new user `%s`' % username,
627 627 user=jsonify(usr.get_api_data())
628 628 )
629 629 try:
630 630 expected = ret
631 631 self._compare_ok(id_, expected, given=response.body)
632 632 finally:
633 633 fixture.destroy_user(usr.user_id)
634 634
635 635 @mock.patch.object(UserModel, 'create_or_update', crash)
636 636 def test_api_create_user_when_exception_happened(self):
637 637
638 638 username = 'test_new_api_user'
639 639 email = username + "@foo.com"
640 640
641 641 id_, params = _build_data(self.apikey, 'create_user',
642 642 username=username,
643 643 email=email,
644 644 password='trololo')
645 645 response = api_call(self, params)
646 646 expected = 'failed to create user `%s`' % username
647 647 self._compare_error(id_, expected, given=response.body)
648 648
649 649 def test_api_delete_user(self):
650 650 usr = UserModel().create_or_update(username=u'test_user',
651 651 password=u'qweqwe',
652 652 email=u'u232@example.com',
653 653 firstname=u'u1', lastname=u'u1')
654 654 Session().commit()
655 655 username = usr.username
656 656 email = usr.email
657 657 usr_id = usr.user_id
658 658 ## DELETE THIS USER NOW
659 659
660 660 id_, params = _build_data(self.apikey, 'delete_user',
661 661 userid=username, )
662 662 response = api_call(self, params)
663 663
664 664 ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username),
665 665 'user': None}
666 666 expected = ret
667 667 self._compare_ok(id_, expected, given=response.body)
668 668
669 669 @mock.patch.object(UserModel, 'delete', crash)
670 670 def test_api_delete_user_when_exception_happened(self):
671 671 usr = UserModel().create_or_update(username=u'test_user',
672 672 password=u'qweqwe',
673 673 email=u'u232@example.com',
674 674 firstname=u'u1', lastname=u'u1')
675 675 Session().commit()
676 676 username = usr.username
677 677
678 678 id_, params = _build_data(self.apikey, 'delete_user',
679 679 userid=username, )
680 680 response = api_call(self, params)
681 681 ret = 'failed to delete user ID:%s %s' % (usr.user_id,
682 682 usr.username)
683 683 expected = ret
684 684 self._compare_error(id_, expected, given=response.body)
685 685
686 686 @parameterized.expand([('firstname', 'new_username'),
687 687 ('lastname', 'new_username'),
688 688 ('email', 'new_username'),
689 689 ('admin', True),
690 690 ('admin', False),
691 691 ('extern_type', 'ldap'),
692 692 ('extern_type', None),
693 693 ('extern_name', 'test'),
694 694 ('extern_name', None),
695 695 ('active', False),
696 696 ('active', True),
697 697 ('password', 'newpass')
698 698 ])
699 699 def test_api_update_user(self, name, expected):
700 700 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
701 701 kw = {name: expected,
702 702 'userid': usr.user_id}
703 703 id_, params = _build_data(self.apikey, 'update_user', **kw)
704 704 response = api_call(self, params)
705 705
706 706 ret = {
707 707 'msg': 'updated user ID:%s %s' % (
708 708 usr.user_id, self.TEST_USER_LOGIN),
709 709 'user': jsonify(UserModel() \
710 710 .get_by_username(self.TEST_USER_LOGIN) \
711 711 .get_api_data())
712 712 }
713 713
714 714 expected = ret
715 715 self._compare_ok(id_, expected, given=response.body)
716 716
717 717 def test_api_update_user_no_changed_params(self):
718 718 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
719 719 ret = jsonify(usr.get_api_data())
720 720 id_, params = _build_data(self.apikey, 'update_user',
721 721 userid=TEST_USER_ADMIN_LOGIN)
722 722
723 723 response = api_call(self, params)
724 724 ret = {
725 725 'msg': 'updated user ID:%s %s' % (
726 726 usr.user_id, TEST_USER_ADMIN_LOGIN),
727 727 'user': ret
728 728 }
729 729 expected = ret
730 730 self._compare_ok(id_, expected, given=response.body)
731 731
732 732 def test_api_update_user_by_user_id(self):
733 733 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
734 734 ret = jsonify(usr.get_api_data())
735 735 id_, params = _build_data(self.apikey, 'update_user',
736 736 userid=usr.user_id)
737 737
738 738 response = api_call(self, params)
739 739 ret = {
740 740 'msg': 'updated user ID:%s %s' % (
741 741 usr.user_id, TEST_USER_ADMIN_LOGIN),
742 742 'user': ret
743 743 }
744 744 expected = ret
745 745 self._compare_ok(id_, expected, given=response.body)
746 746
747 747 def test_api_update_user_default_user(self):
748 748 usr = User.get_default_user()
749 749 id_, params = _build_data(self.apikey, 'update_user',
750 750 userid=usr.user_id)
751 751
752 752 response = api_call(self, params)
753 753 expected = 'editing default user is forbidden'
754 754 self._compare_error(id_, expected, given=response.body)
755 755
756 756 @mock.patch.object(UserModel, 'update_user', crash)
757 757 def test_api_update_user_when_exception_happens(self):
758 758 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
759 759 ret = jsonify(usr.get_api_data())
760 760 id_, params = _build_data(self.apikey, 'update_user',
761 761 userid=usr.user_id)
762 762
763 763 response = api_call(self, params)
764 764 ret = 'failed to update user `%s`' % usr.user_id
765 765
766 766 expected = ret
767 767 self._compare_error(id_, expected, given=response.body)
768 768
769 769 def test_api_get_repo(self):
770 770 new_group = 'some_new_group'
771 771 make_user_group(new_group)
772 772 RepoModel().grant_user_group_permission(repo=self.REPO,
773 773 group_name=new_group,
774 774 perm='repository.read')
775 775 Session().commit()
776 776 id_, params = _build_data(self.apikey, 'get_repo',
777 777 repoid=self.REPO)
778 778 response = api_call(self, params)
779 779
780 780 repo = RepoModel().get_by_repo_name(self.REPO)
781 781 ret = repo.get_api_data()
782 782
783 783 members = []
784 784 followers = []
785 785 for user in repo.repo_to_perm:
786 786 perm = user.permission.permission_name
787 787 user = user.user
788 788 user_data = {'name': user.username, 'type': "user",
789 789 'permission': perm}
790 790 members.append(user_data)
791 791
792 792 for user_group in repo.users_group_to_perm:
793 793 perm = user_group.permission.permission_name
794 794 user_group = user_group.users_group
795 795 user_group_data = {'name': user_group.users_group_name,
796 796 'type': "user_group", 'permission': perm}
797 797 members.append(user_group_data)
798 798
799 799 for user in repo.followers:
800 800 followers.append(user.user.get_api_data())
801 801
802 802 ret['members'] = members
803 803 ret['followers'] = followers
804 804
805 805 expected = ret
806 806 self._compare_ok(id_, expected, given=response.body)
807 807 fixture.destroy_user_group(new_group)
808 808
809 809 @parameterized.expand([
810 810 ('repository.admin',),
811 811 ('repository.write',),
812 812 ('repository.read',),
813 813 ])
814 814 def test_api_get_repo_by_non_admin(self, grant_perm):
815 815 RepoModel().grant_user_permission(repo=self.REPO,
816 816 user=self.TEST_USER_LOGIN,
817 817 perm=grant_perm)
818 818 Session().commit()
819 819 id_, params = _build_data(self.apikey_regular, 'get_repo',
820 820 repoid=self.REPO)
821 821 response = api_call(self, params)
822 822
823 823 repo = RepoModel().get_by_repo_name(self.REPO)
824 824 ret = repo.get_api_data()
825 825
826 826 members = []
827 827 followers = []
828 828 self.assertEqual(2, len(repo.repo_to_perm))
829 829 for user in repo.repo_to_perm:
830 830 perm = user.permission.permission_name
831 831 user_obj = user.user
832 832 user_data = {'name': user_obj.username, 'type': "user",
833 833 'permission': perm}
834 834 members.append(user_data)
835 835
836 836 for user_group in repo.users_group_to_perm:
837 837 perm = user_group.permission.permission_name
838 838 user_group_obj = user_group.users_group
839 839 user_group_data = {'name': user_group_obj.users_group_name,
840 840 'type': "user_group", 'permission': perm}
841 841 members.append(user_group_data)
842 842
843 843 for user in repo.followers:
844 844 followers.append(user.user.get_api_data())
845 845
846 846 ret['members'] = members
847 847 ret['followers'] = followers
848 848
849 849 expected = ret
850 850 try:
851 851 self._compare_ok(id_, expected, given=response.body)
852 852 finally:
853 853 RepoModel().revoke_user_permission(self.REPO, self.TEST_USER_LOGIN)
854 854
855 855 def test_api_get_repo_by_non_admin_no_permission_to_repo(self):
856 856 RepoModel().grant_user_permission(repo=self.REPO,
857 857 user=self.TEST_USER_LOGIN,
858 858 perm='repository.none')
859 859
860 860 id_, params = _build_data(self.apikey_regular, 'get_repo',
861 861 repoid=self.REPO)
862 862 response = api_call(self, params)
863 863
864 864 expected = 'repository `%s` does not exist' % (self.REPO)
865 865 self._compare_error(id_, expected, given=response.body)
866 866
867 867 def test_api_get_repo_that_doesn_not_exist(self):
868 868 id_, params = _build_data(self.apikey, 'get_repo',
869 869 repoid='no-such-repo')
870 870 response = api_call(self, params)
871 871
872 872 ret = 'repository `%s` does not exist' % 'no-such-repo'
873 873 expected = ret
874 874 self._compare_error(id_, expected, given=response.body)
875 875
876 876 def test_api_get_repos(self):
877 877 id_, params = _build_data(self.apikey, 'get_repos')
878 878 response = api_call(self, params)
879 879
880 880 result = []
881 881 for repo in RepoModel().get_all():
882 882 result.append(repo.get_api_data())
883 883 ret = jsonify(result)
884 884
885 885 expected = ret
886 886 self._compare_ok(id_, expected, given=response.body)
887 887
888 888 def test_api_get_repos_non_admin(self):
889 889 id_, params = _build_data(self.apikey_regular, 'get_repos')
890 890 response = api_call(self, params)
891 891
892 892 result = []
893 893 for repo in RepoModel().get_all_user_repos(self.TEST_USER_LOGIN):
894 894 result.append(repo.get_api_data())
895 895 ret = jsonify(result)
896 896
897 897 expected = ret
898 898 self._compare_ok(id_, expected, given=response.body)
899 899
900 900 @parameterized.expand([('all', 'all'),
901 901 ('dirs', 'dirs'),
902 902 ('files', 'files'), ])
903 903 def test_api_get_repo_nodes(self, name, ret_type):
904 904 rev = 'tip'
905 905 path = '/'
906 906 id_, params = _build_data(self.apikey, 'get_repo_nodes',
907 907 repoid=self.REPO, revision=rev,
908 908 root_path=path,
909 909 ret_type=ret_type)
910 910 response = api_call(self, params)
911 911
912 912 # we don't the actual return types here since it's tested somewhere
913 913 # else
914 914 expected = response.json['result']
915 915 self._compare_ok(id_, expected, given=response.body)
916 916
917 917 def test_api_get_repo_nodes_bad_revisions(self):
918 918 rev = 'i-dont-exist'
919 919 path = '/'
920 920 id_, params = _build_data(self.apikey, 'get_repo_nodes',
921 921 repoid=self.REPO, revision=rev,
922 922 root_path=path, )
923 923 response = api_call(self, params)
924 924
925 925 expected = 'failed to get repo: `%s` nodes' % self.REPO
926 926 self._compare_error(id_, expected, given=response.body)
927 927
928 928 def test_api_get_repo_nodes_bad_path(self):
929 929 rev = 'tip'
930 930 path = '/idontexits'
931 931 id_, params = _build_data(self.apikey, 'get_repo_nodes',
932 932 repoid=self.REPO, revision=rev,
933 933 root_path=path, )
934 934 response = api_call(self, params)
935 935
936 936 expected = 'failed to get repo: `%s` nodes' % self.REPO
937 937 self._compare_error(id_, expected, given=response.body)
938 938
939 939 def test_api_get_repo_nodes_bad_ret_type(self):
940 940 rev = 'tip'
941 941 path = '/'
942 942 ret_type = 'error'
943 943 id_, params = _build_data(self.apikey, 'get_repo_nodes',
944 944 repoid=self.REPO, revision=rev,
945 945 root_path=path,
946 946 ret_type=ret_type)
947 947 response = api_call(self, params)
948 948
949 949 expected = ('ret_type must be one of %s'
950 950 % (','.join(['files', 'dirs', 'all'])))
951 951 self._compare_error(id_, expected, given=response.body)
952 952
953 953 @parameterized.expand([('all', 'all', 'repository.write'),
954 954 ('dirs', 'dirs', 'repository.admin'),
955 955 ('files', 'files', 'repository.read'), ])
956 956 def test_api_get_repo_nodes_by_regular_user(self, name, ret_type, grant_perm):
957 957 RepoModel().grant_user_permission(repo=self.REPO,
958 958 user=self.TEST_USER_LOGIN,
959 959 perm=grant_perm)
960 960 Session().commit()
961 961
962 962 rev = 'tip'
963 963 path = '/'
964 964 id_, params = _build_data(self.apikey_regular, 'get_repo_nodes',
965 965 repoid=self.REPO, revision=rev,
966 966 root_path=path,
967 967 ret_type=ret_type)
968 968 response = api_call(self, params)
969 969
970 970 # we don't the actual return types here since it's tested somewhere
971 971 # else
972 972 expected = response.json['result']
973 973 try:
974 974 self._compare_ok(id_, expected, given=response.body)
975 975 finally:
976 976 RepoModel().revoke_user_permission(self.REPO, self.TEST_USER_LOGIN)
977 977
978 978 def test_api_create_repo(self):
979 979 repo_name = 'api-repo'
980 980 id_, params = _build_data(self.apikey, 'create_repo',
981 981 repo_name=repo_name,
982 982 owner=TEST_USER_ADMIN_LOGIN,
983 983 repo_type=self.REPO_TYPE,
984 984 )
985 985 response = api_call(self, params)
986 986
987 987 repo = RepoModel().get_by_repo_name(repo_name)
988 988 self.assertNotEqual(repo, None)
989 989 ret = {
990 990 'msg': 'Created new repository `%s`' % repo_name,
991 991 'success': True,
992 992 'task': None,
993 993 }
994 994 expected = ret
995 995 self._compare_ok(id_, expected, given=response.body)
996 996 fixture.destroy_repo(repo_name)
997 997
998 998 def test_api_create_repo_in_group(self):
999 999 repo_name = 'my_gr/api-repo'
1000 1000 id_, params = _build_data(self.apikey, 'create_repo',
1001 1001 repo_name=repo_name,
1002 1002 owner=TEST_USER_ADMIN_LOGIN,
1003 1003 repo_type=self.REPO_TYPE,)
1004 1004 response = api_call(self, params)
1005 1005 print params
1006 1006 repo = RepoModel().get_by_repo_name(repo_name)
1007 1007 self.assertNotEqual(repo, None)
1008 1008 ret = {
1009 1009 'msg': 'Created new repository `%s`' % repo_name,
1010 1010 'success': True,
1011 1011 'task': None,
1012 1012 }
1013 1013 expected = ret
1014 1014 self._compare_ok(id_, expected, given=response.body)
1015 1015 fixture.destroy_repo(repo_name)
1016 1016 fixture.destroy_repo_group('my_gr')
1017 1017
1018 1018 def test_api_create_repo_unknown_owner(self):
1019 1019 repo_name = 'api-repo'
1020 1020 owner = 'i-dont-exist'
1021 1021 id_, params = _build_data(self.apikey, 'create_repo',
1022 1022 repo_name=repo_name,
1023 1023 owner=owner,
1024 1024 repo_type=self.REPO_TYPE,
1025 1025 )
1026 1026 response = api_call(self, params)
1027 1027 expected = 'user `%s` does not exist' % owner
1028 1028 self._compare_error(id_, expected, given=response.body)
1029 1029
1030 1030 def test_api_create_repo_dont_specify_owner(self):
1031 1031 repo_name = 'api-repo'
1032 1032 owner = 'i-dont-exist'
1033 1033 id_, params = _build_data(self.apikey, 'create_repo',
1034 1034 repo_name=repo_name,
1035 1035 repo_type=self.REPO_TYPE,
1036 1036 )
1037 1037 response = api_call(self, params)
1038 1038
1039 1039 repo = RepoModel().get_by_repo_name(repo_name)
1040 1040 self.assertNotEqual(repo, None)
1041 1041 ret = {
1042 1042 'msg': 'Created new repository `%s`' % repo_name,
1043 1043 'success': True,
1044 1044 'task': None,
1045 1045 }
1046 1046 expected = ret
1047 1047 self._compare_ok(id_, expected, given=response.body)
1048 1048 fixture.destroy_repo(repo_name)
1049 1049
1050 1050 def test_api_create_repo_by_non_admin(self):
1051 1051 repo_name = 'api-repo'
1052 1052 owner = 'i-dont-exist'
1053 1053 id_, params = _build_data(self.apikey_regular, 'create_repo',
1054 1054 repo_name=repo_name,
1055 1055 repo_type=self.REPO_TYPE,
1056 1056 )
1057 1057 response = api_call(self, params)
1058 1058
1059 1059 repo = RepoModel().get_by_repo_name(repo_name)
1060 1060 self.assertNotEqual(repo, None)
1061 1061 ret = {
1062 1062 'msg': 'Created new repository `%s`' % repo_name,
1063 1063 'success': True,
1064 1064 'task': None,
1065 1065 }
1066 1066 expected = ret
1067 1067 self._compare_ok(id_, expected, given=response.body)
1068 1068 fixture.destroy_repo(repo_name)
1069 1069
1070 1070 def test_api_create_repo_by_non_admin_specify_owner(self):
1071 1071 repo_name = 'api-repo'
1072 1072 owner = 'i-dont-exist'
1073 1073 id_, params = _build_data(self.apikey_regular, 'create_repo',
1074 1074 repo_name=repo_name,
1075 1075 repo_type=self.REPO_TYPE,
1076 1076 owner=owner)
1077 1077 response = api_call(self, params)
1078 1078
1079 1079 expected = 'Only Kallithea admin can specify `owner` param'
1080 1080 self._compare_error(id_, expected, given=response.body)
1081 1081 fixture.destroy_repo(repo_name)
1082 1082
1083 1083 def test_api_create_repo_exists(self):
1084 1084 repo_name = self.REPO
1085 1085 id_, params = _build_data(self.apikey, 'create_repo',
1086 1086 repo_name=repo_name,
1087 1087 owner=TEST_USER_ADMIN_LOGIN,
1088 1088 repo_type=self.REPO_TYPE,)
1089 1089 response = api_call(self, params)
1090 1090 expected = "repo `%s` already exist" % repo_name
1091 1091 self._compare_error(id_, expected, given=response.body)
1092 1092
1093 1093 @mock.patch.object(RepoModel, 'create', crash)
1094 1094 def test_api_create_repo_exception_occurred(self):
1095 1095 repo_name = 'api-repo'
1096 1096 id_, params = _build_data(self.apikey, 'create_repo',
1097 1097 repo_name=repo_name,
1098 1098 owner=TEST_USER_ADMIN_LOGIN,
1099 1099 repo_type=self.REPO_TYPE,)
1100 1100 response = api_call(self, params)
1101 1101 expected = 'failed to create repository `%s`' % repo_name
1102 1102 self._compare_error(id_, expected, given=response.body)
1103 1103
1104 1104 @parameterized.expand([
1105 1105 ('owner', {'owner': TEST_USER_REGULAR_LOGIN}),
1106 1106 ('description', {'description': 'new description'}),
1107 1107 ('active', {'active': True}),
1108 1108 ('active', {'active': False}),
1109 1109 ('clone_uri', {'clone_uri': 'http://foo.com/repo'}),
1110 1110 ('clone_uri', {'clone_uri': None}),
1111 1111 ('landing_rev', {'landing_rev': 'branch:master'}),
1112 1112 ('enable_statistics', {'enable_statistics': True}),
1113 1113 ('enable_locking', {'enable_locking': True}),
1114 1114 ('enable_downloads', {'enable_downloads': True}),
1115 1115 ('name', {'name': 'new_repo_name'}),
1116 1116 ('repo_group', {'group': 'test_group_for_update'}),
1117 1117 ])
1118 1118 def test_api_update_repo(self, changing_attr, updates):
1119 1119 repo_name = 'api_update_me'
1120 1120 repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1121 1121 if changing_attr == 'repo_group':
1122 1122 fixture.create_repo_group(updates['group'])
1123 1123
1124 1124 id_, params = _build_data(self.apikey, 'update_repo',
1125 1125 repoid=repo_name, **updates)
1126 1126 response = api_call(self, params)
1127 1127 if changing_attr == 'name':
1128 1128 repo_name = updates['name']
1129 1129 if changing_attr == 'repo_group':
1130 1130 repo_name = '/'.join([updates['group'], repo_name])
1131 1131 try:
1132 1132 expected = {
1133 1133 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo_name),
1134 1134 'repository': repo.get_api_data()
1135 1135 }
1136 1136 self._compare_ok(id_, expected, given=response.body)
1137 1137 finally:
1138 1138 fixture.destroy_repo(repo_name)
1139 1139 if changing_attr == 'repo_group':
1140 1140 fixture.destroy_repo_group(updates['group'])
1141 1141
1142 1142 def test_api_update_repo_repo_group_does_not_exist(self):
1143 1143 repo_name = 'admin_owned'
1144 1144 fixture.create_repo(repo_name)
1145 1145 updates = {'group': 'test_group_for_update'}
1146 1146 id_, params = _build_data(self.apikey, 'update_repo',
1147 1147 repoid=repo_name, **updates)
1148 1148 response = api_call(self, params)
1149 1149 try:
1150 1150 expected = 'repository group `%s` does not exist' % updates['group']
1151 1151 self._compare_error(id_, expected, given=response.body)
1152 1152 finally:
1153 1153 fixture.destroy_repo(repo_name)
1154 1154
1155 1155 def test_api_update_repo_regular_user_not_allowed(self):
1156 1156 repo_name = 'admin_owned'
1157 1157 fixture.create_repo(repo_name)
1158 1158 updates = {'active': False}
1159 1159 id_, params = _build_data(self.apikey_regular, 'update_repo',
1160 1160 repoid=repo_name, **updates)
1161 1161 response = api_call(self, params)
1162 1162 try:
1163 1163 expected = 'repository `%s` does not exist' % repo_name
1164 1164 self._compare_error(id_, expected, given=response.body)
1165 1165 finally:
1166 1166 fixture.destroy_repo(repo_name)
1167 1167
1168 1168 @mock.patch.object(RepoModel, 'update', crash)
1169 1169 def test_api_update_repo_exception_occurred(self):
1170 1170 repo_name = 'api_update_me'
1171 1171 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1172 1172 id_, params = _build_data(self.apikey, 'update_repo',
1173 1173 repoid=repo_name, owner=TEST_USER_ADMIN_LOGIN,)
1174 1174 response = api_call(self, params)
1175 1175 try:
1176 1176 expected = 'failed to update repo `%s`' % repo_name
1177 1177 self._compare_error(id_, expected, given=response.body)
1178 1178 finally:
1179 1179 fixture.destroy_repo(repo_name)
1180 1180
1181 1181 def test_api_delete_repo(self):
1182 1182 repo_name = 'api_delete_me'
1183 1183 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1184 1184
1185 1185 id_, params = _build_data(self.apikey, 'delete_repo',
1186 1186 repoid=repo_name, )
1187 1187 response = api_call(self, params)
1188 1188
1189 1189 ret = {
1190 1190 'msg': 'Deleted repository `%s`' % repo_name,
1191 1191 'success': True
1192 1192 }
1193 1193 try:
1194 1194 expected = ret
1195 1195 self._compare_ok(id_, expected, given=response.body)
1196 1196 finally:
1197 1197 fixture.destroy_repo(repo_name)
1198 1198
1199 1199 def test_api_delete_repo_by_non_admin(self):
1200 1200 repo_name = 'api_delete_me'
1201 1201 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
1202 1202 cur_user=self.TEST_USER_LOGIN)
1203 1203 id_, params = _build_data(self.apikey_regular, 'delete_repo',
1204 1204 repoid=repo_name, )
1205 1205 response = api_call(self, params)
1206 1206
1207 1207 ret = {
1208 1208 'msg': 'Deleted repository `%s`' % repo_name,
1209 1209 'success': True
1210 1210 }
1211 1211 try:
1212 1212 expected = ret
1213 1213 self._compare_ok(id_, expected, given=response.body)
1214 1214 finally:
1215 1215 fixture.destroy_repo(repo_name)
1216 1216
1217 1217 def test_api_delete_repo_by_non_admin_no_permission(self):
1218 1218 repo_name = 'api_delete_me'
1219 1219 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1220 1220 try:
1221 1221 id_, params = _build_data(self.apikey_regular, 'delete_repo',
1222 1222 repoid=repo_name, )
1223 1223 response = api_call(self, params)
1224 1224 expected = 'repository `%s` does not exist' % (repo_name)
1225 1225 self._compare_error(id_, expected, given=response.body)
1226 1226 finally:
1227 1227 fixture.destroy_repo(repo_name)
1228 1228
1229 1229 def test_api_delete_repo_exception_occurred(self):
1230 1230 repo_name = 'api_delete_me'
1231 1231 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1232 1232 try:
1233 1233 with mock.patch.object(RepoModel, 'delete', crash):
1234 1234 id_, params = _build_data(self.apikey, 'delete_repo',
1235 1235 repoid=repo_name, )
1236 1236 response = api_call(self, params)
1237 1237
1238 1238 expected = 'failed to delete repository `%s`' % repo_name
1239 1239 self._compare_error(id_, expected, given=response.body)
1240 1240 finally:
1241 1241 fixture.destroy_repo(repo_name)
1242 1242
1243 1243 def test_api_fork_repo(self):
1244 1244 fork_name = 'api-repo-fork'
1245 1245 id_, params = _build_data(self.apikey, 'fork_repo',
1246 1246 repoid=self.REPO,
1247 1247 fork_name=fork_name,
1248 1248 owner=TEST_USER_ADMIN_LOGIN,
1249 1249 )
1250 1250 response = api_call(self, params)
1251 1251
1252 1252 ret = {
1253 1253 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
1254 1254 fork_name),
1255 1255 'success': True,
1256 1256 'task': None,
1257 1257 }
1258 1258 expected = ret
1259 1259 self._compare_ok(id_, expected, given=response.body)
1260 1260 fixture.destroy_repo(fork_name)
1261 1261
1262 1262 def test_api_fork_repo_non_admin(self):
1263 1263 fork_name = 'api-repo-fork'
1264 1264 id_, params = _build_data(self.apikey_regular, 'fork_repo',
1265 1265 repoid=self.REPO,
1266 1266 fork_name=fork_name,
1267 1267 )
1268 1268 response = api_call(self, params)
1269 1269
1270 1270 ret = {
1271 1271 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
1272 1272 fork_name),
1273 1273 'success': True,
1274 1274 'task': None,
1275 1275 }
1276 1276 expected = ret
1277 1277 self._compare_ok(id_, expected, given=response.body)
1278 1278 fixture.destroy_repo(fork_name)
1279 1279
1280 1280 def test_api_fork_repo_non_admin_specify_owner(self):
1281 1281 fork_name = 'api-repo-fork'
1282 1282 id_, params = _build_data(self.apikey_regular, 'fork_repo',
1283 1283 repoid=self.REPO,
1284 1284 fork_name=fork_name,
1285 1285 owner=TEST_USER_ADMIN_LOGIN,
1286 1286 )
1287 1287 response = api_call(self, params)
1288 1288 expected = 'Only Kallithea admin can specify `owner` param'
1289 1289 self._compare_error(id_, expected, given=response.body)
1290 1290 fixture.destroy_repo(fork_name)
1291 1291
1292 1292 def test_api_fork_repo_non_admin_no_permission_to_fork(self):
1293 1293 RepoModel().grant_user_permission(repo=self.REPO,
1294 1294 user=self.TEST_USER_LOGIN,
1295 1295 perm='repository.none')
1296 1296 fork_name = 'api-repo-fork'
1297 1297 id_, params = _build_data(self.apikey_regular, 'fork_repo',
1298 1298 repoid=self.REPO,
1299 1299 fork_name=fork_name,
1300 1300 )
1301 1301 response = api_call(self, params)
1302 1302 expected = 'repository `%s` does not exist' % (self.REPO)
1303 1303 self._compare_error(id_, expected, given=response.body)
1304 1304 fixture.destroy_repo(fork_name)
1305 1305
1306 1306 def test_api_fork_repo_unknown_owner(self):
1307 1307 fork_name = 'api-repo-fork'
1308 1308 owner = 'i-dont-exist'
1309 1309 id_, params = _build_data(self.apikey, 'fork_repo',
1310 1310 repoid=self.REPO,
1311 1311 fork_name=fork_name,
1312 1312 owner=owner,
1313 1313 )
1314 1314 response = api_call(self, params)
1315 1315 expected = 'user `%s` does not exist' % owner
1316 1316 self._compare_error(id_, expected, given=response.body)
1317 1317
1318 1318 def test_api_fork_repo_fork_exists(self):
1319 1319 fork_name = 'api-repo-fork'
1320 1320 fixture.create_fork(self.REPO, fork_name)
1321 1321
1322 1322 try:
1323 1323 fork_name = 'api-repo-fork'
1324 1324
1325 1325 id_, params = _build_data(self.apikey, 'fork_repo',
1326 1326 repoid=self.REPO,
1327 1327 fork_name=fork_name,
1328 1328 owner=TEST_USER_ADMIN_LOGIN,
1329 1329 )
1330 1330 response = api_call(self, params)
1331 1331
1332 1332 expected = "fork `%s` already exist" % fork_name
1333 1333 self._compare_error(id_, expected, given=response.body)
1334 1334 finally:
1335 1335 fixture.destroy_repo(fork_name)
1336 1336
1337 1337 def test_api_fork_repo_repo_exists(self):
1338 1338 fork_name = self.REPO
1339 1339
1340 1340 id_, params = _build_data(self.apikey, 'fork_repo',
1341 1341 repoid=self.REPO,
1342 1342 fork_name=fork_name,
1343 1343 owner=TEST_USER_ADMIN_LOGIN,
1344 1344 )
1345 1345 response = api_call(self, params)
1346 1346
1347 1347 expected = "repo `%s` already exist" % fork_name
1348 1348 self._compare_error(id_, expected, given=response.body)
1349 1349
1350 1350 @mock.patch.object(RepoModel, 'create_fork', crash)
1351 1351 def test_api_fork_repo_exception_occurred(self):
1352 1352 fork_name = 'api-repo-fork'
1353 1353 id_, params = _build_data(self.apikey, 'fork_repo',
1354 1354 repoid=self.REPO,
1355 1355 fork_name=fork_name,
1356 1356 owner=TEST_USER_ADMIN_LOGIN,
1357 1357 )
1358 1358 response = api_call(self, params)
1359 1359
1360 1360 expected = 'failed to fork repository `%s` as `%s`' % (self.REPO,
1361 1361 fork_name)
1362 1362 self._compare_error(id_, expected, given=response.body)
1363 1363
1364 1364 def test_api_get_user_group(self):
1365 1365 id_, params = _build_data(self.apikey, 'get_user_group',
1366 1366 usergroupid=TEST_USER_GROUP)
1367 1367 response = api_call(self, params)
1368 1368
1369 1369 user_group = UserGroupModel().get_group(TEST_USER_GROUP)
1370 1370 members = []
1371 1371 for user in user_group.members:
1372 1372 user = user.user
1373 1373 members.append(user.get_api_data())
1374 1374
1375 1375 ret = user_group.get_api_data()
1376 1376 ret['members'] = members
1377 1377 expected = ret
1378 1378 self._compare_ok(id_, expected, given=response.body)
1379 1379
1380 1380 def test_api_get_user_groups(self):
1381 1381 gr_name = 'test_user_group2'
1382 1382 make_user_group(gr_name)
1383 1383
1384 1384 id_, params = _build_data(self.apikey, 'get_user_groups', )
1385 1385 response = api_call(self, params)
1386 1386
1387 1387 try:
1388 1388 expected = []
1389 1389 for gr_name in [TEST_USER_GROUP, 'test_user_group2']:
1390 1390 user_group = UserGroupModel().get_group(gr_name)
1391 1391 ret = user_group.get_api_data()
1392 1392 expected.append(ret)
1393 1393 self._compare_ok(id_, expected, given=response.body)
1394 1394 finally:
1395 1395 fixture.destroy_user_group(gr_name)
1396 1396
1397 1397 def test_api_create_user_group(self):
1398 1398 group_name = 'some_new_group'
1399 1399 id_, params = _build_data(self.apikey, 'create_user_group',
1400 1400 group_name=group_name)
1401 1401 response = api_call(self, params)
1402 1402
1403 1403 ret = {
1404 1404 'msg': 'created new user group `%s`' % group_name,
1405 1405 'user_group': jsonify(UserGroupModel() \
1406 1406 .get_by_name(group_name) \
1407 1407 .get_api_data())
1408 1408 }
1409 1409 expected = ret
1410 1410 self._compare_ok(id_, expected, given=response.body)
1411 1411
1412 1412 fixture.destroy_user_group(group_name)
1413 1413
1414 1414 def test_api_get_user_group_that_exist(self):
1415 1415 id_, params = _build_data(self.apikey, 'create_user_group',
1416 1416 group_name=TEST_USER_GROUP)
1417 1417 response = api_call(self, params)
1418 1418
1419 1419 expected = "user group `%s` already exist" % TEST_USER_GROUP
1420 1420 self._compare_error(id_, expected, given=response.body)
1421 1421
1422 1422 @mock.patch.object(UserGroupModel, 'create', crash)
1423 1423 def test_api_get_user_group_exception_occurred(self):
1424 1424 group_name = 'exception_happens'
1425 1425 id_, params = _build_data(self.apikey, 'create_user_group',
1426 1426 group_name=group_name)
1427 1427 response = api_call(self, params)
1428 1428
1429 1429 expected = 'failed to create group `%s`' % group_name
1430 1430 self._compare_error(id_, expected, given=response.body)
1431 1431
1432 1432 @parameterized.expand([('group_name', {'group_name': 'new_group_name'}),
1433 1433 ('group_name', {'group_name': 'test_group_for_update'}),
1434 1434 ('owner', {'owner': TEST_USER_REGULAR_LOGIN}),
1435 1435 ('active', {'active': False}),
1436 1436 ('active', {'active': True})])
1437 1437 def test_api_update_user_group(self, changing_attr, updates):
1438 1438 gr_name = 'test_group_for_update'
1439 1439 user_group = fixture.create_user_group(gr_name)
1440 1440 id_, params = _build_data(self.apikey, 'update_user_group',
1441 1441 usergroupid=gr_name, **updates)
1442 1442 response = api_call(self, params)
1443 1443 try:
1444 1444 expected = {
1445 1445 'msg': 'updated user group ID:%s %s' % (user_group.users_group_id,
1446 1446 user_group.users_group_name),
1447 1447 'user_group': user_group.get_api_data()
1448 1448 }
1449 1449 self._compare_ok(id_, expected, given=response.body)
1450 1450 finally:
1451 1451 if changing_attr == 'group_name':
1452 1452 # switch to updated name for proper cleanup
1453 1453 gr_name = updates['group_name']
1454 1454 fixture.destroy_user_group(gr_name)
1455 1455
1456 1456 @mock.patch.object(UserGroupModel, 'update', crash)
1457 1457 def test_api_update_user_group_exception_occurred(self):
1458 1458 gr_name = 'test_group'
1459 1459 fixture.create_user_group(gr_name)
1460 1460 id_, params = _build_data(self.apikey, 'update_user_group',
1461 1461 usergroupid=gr_name)
1462 1462 response = api_call(self, params)
1463 1463 try:
1464 1464 expected = 'failed to update user group `%s`' % gr_name
1465 1465 self._compare_error(id_, expected, given=response.body)
1466 1466 finally:
1467 1467 fixture.destroy_user_group(gr_name)
1468 1468
1469 1469 def test_api_add_user_to_user_group(self):
1470 1470 gr_name = 'test_group'
1471 1471 fixture.create_user_group(gr_name)
1472 1472 id_, params = _build_data(self.apikey, 'add_user_to_user_group',
1473 1473 usergroupid=gr_name,
1474 1474 userid=TEST_USER_ADMIN_LOGIN)
1475 1475 response = api_call(self, params)
1476 1476 try:
1477 1477 expected = {
1478 1478 'msg': 'added member `%s` to user group `%s`' % (
1479 1479 TEST_USER_ADMIN_LOGIN, gr_name),
1480 1480 'success': True
1481 1481 }
1482 1482 self._compare_ok(id_, expected, given=response.body)
1483 1483 finally:
1484 1484 fixture.destroy_user_group(gr_name)
1485 1485
1486 1486 def test_api_add_user_to_user_group_that_doesnt_exist(self):
1487 1487 id_, params = _build_data(self.apikey, 'add_user_to_user_group',
1488 1488 usergroupid='false-group',
1489 1489 userid=TEST_USER_ADMIN_LOGIN)
1490 1490 response = api_call(self, params)
1491 1491
1492 1492 expected = 'user group `%s` does not exist' % 'false-group'
1493 1493 self._compare_error(id_, expected, given=response.body)
1494 1494
1495 1495 @mock.patch.object(UserGroupModel, 'add_user_to_group', crash)
1496 1496 def test_api_add_user_to_user_group_exception_occurred(self):
1497 1497 gr_name = 'test_group'
1498 1498 fixture.create_user_group(gr_name)
1499 1499 id_, params = _build_data(self.apikey, 'add_user_to_user_group',
1500 1500 usergroupid=gr_name,
1501 1501 userid=TEST_USER_ADMIN_LOGIN)
1502 1502 response = api_call(self, params)
1503 1503
1504 1504 try:
1505 1505 expected = 'failed to add member to user group `%s`' % gr_name
1506 1506 self._compare_error(id_, expected, given=response.body)
1507 1507 finally:
1508 1508 fixture.destroy_user_group(gr_name)
1509 1509
1510 1510 def test_api_remove_user_from_user_group(self):
1511 1511 gr_name = 'test_group_3'
1512 1512 gr = fixture.create_user_group(gr_name)
1513 1513 UserGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1514 1514 Session().commit()
1515 1515 id_, params = _build_data(self.apikey, 'remove_user_from_user_group',
1516 1516 usergroupid=gr_name,
1517 1517 userid=TEST_USER_ADMIN_LOGIN)
1518 1518 response = api_call(self, params)
1519 1519
1520 1520 try:
1521 1521 expected = {
1522 1522 'msg': 'removed member `%s` from user group `%s`' % (
1523 1523 TEST_USER_ADMIN_LOGIN, gr_name
1524 1524 ),
1525 1525 'success': True}
1526 1526 self._compare_ok(id_, expected, given=response.body)
1527 1527 finally:
1528 1528 fixture.destroy_user_group(gr_name)
1529 1529
1530 1530 @mock.patch.object(UserGroupModel, 'remove_user_from_group', crash)
1531 1531 def test_api_remove_user_from_user_group_exception_occurred(self):
1532 1532 gr_name = 'test_group_3'
1533 1533 gr = fixture.create_user_group(gr_name)
1534 1534 UserGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1535 1535 Session().commit()
1536 1536 id_, params = _build_data(self.apikey, 'remove_user_from_user_group',
1537 1537 usergroupid=gr_name,
1538 1538 userid=TEST_USER_ADMIN_LOGIN)
1539 1539 response = api_call(self, params)
1540 1540 try:
1541 1541 expected = 'failed to remove member from user group `%s`' % gr_name
1542 1542 self._compare_error(id_, expected, given=response.body)
1543 1543 finally:
1544 1544 fixture.destroy_user_group(gr_name)
1545 1545
1546 1546 def test_api_delete_user_group(self):
1547 1547 gr_name = 'test_group'
1548 1548 ugroup = fixture.create_user_group(gr_name)
1549 1549 gr_id = ugroup.users_group_id
1550 1550 id_, params = _build_data(self.apikey, 'delete_user_group',
1551 1551 usergroupid=gr_name,
1552 1552 userid=TEST_USER_ADMIN_LOGIN)
1553 1553 response = api_call(self, params)
1554 1554
1555 1555 try:
1556 1556 expected = {
1557 1557 'user_group': None,
1558 1558 'msg': 'deleted user group ID:%s %s' % (gr_id, gr_name)
1559 1559 }
1560 1560 self._compare_ok(id_, expected, given=response.body)
1561 1561 finally:
1562 1562 if UserGroupModel().get_by_name(gr_name):
1563 1563 fixture.destroy_user_group(gr_name)
1564 1564
1565 1565 def test_api_delete_user_group_that_is_assigned(self):
1566 1566 gr_name = 'test_group'
1567 1567 ugroup = fixture.create_user_group(gr_name)
1568 1568 gr_id = ugroup.users_group_id
1569 1569
1570 1570 ugr_to_perm = RepoModel().grant_user_group_permission(self.REPO, gr_name, 'repository.write')
1571 1571 msg = 'User Group assigned to %s' % ugr_to_perm.repository.repo_name
1572 1572
1573 1573 id_, params = _build_data(self.apikey, 'delete_user_group',
1574 1574 usergroupid=gr_name,
1575 1575 userid=TEST_USER_ADMIN_LOGIN)
1576 1576 response = api_call(self, params)
1577 1577
1578 1578 try:
1579 1579 expected = msg
1580 1580 self._compare_error(id_, expected, given=response.body)
1581 1581 finally:
1582 1582 if UserGroupModel().get_by_name(gr_name):
1583 1583 fixture.destroy_user_group(gr_name)
1584 1584
1585 1585 def test_api_delete_user_group_exception_occurred(self):
1586 1586 gr_name = 'test_group'
1587 1587 ugroup = fixture.create_user_group(gr_name)
1588 1588 gr_id = ugroup.users_group_id
1589 1589 id_, params = _build_data(self.apikey, 'delete_user_group',
1590 1590 usergroupid=gr_name,
1591 1591 userid=TEST_USER_ADMIN_LOGIN)
1592 1592
1593 1593 try:
1594 1594 with mock.patch.object(UserGroupModel, 'delete', crash):
1595 1595 response = api_call(self, params)
1596 1596 expected = 'failed to delete user group ID:%s %s' % (gr_id, gr_name)
1597 1597 self._compare_error(id_, expected, given=response.body)
1598 1598 finally:
1599 1599 fixture.destroy_user_group(gr_name)
1600 1600
1601 1601 @parameterized.expand([('none', 'repository.none'),
1602 1602 ('read', 'repository.read'),
1603 1603 ('write', 'repository.write'),
1604 1604 ('admin', 'repository.admin')])
1605 1605 def test_api_grant_user_permission(self, name, perm):
1606 1606 id_, params = _build_data(self.apikey,
1607 1607 'grant_user_permission',
1608 1608 repoid=self.REPO,
1609 1609 userid=TEST_USER_ADMIN_LOGIN,
1610 1610 perm=perm)
1611 1611 response = api_call(self, params)
1612 1612
1613 1613 ret = {
1614 1614 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % (
1615 1615 perm, TEST_USER_ADMIN_LOGIN, self.REPO
1616 1616 ),
1617 1617 'success': True
1618 1618 }
1619 1619 expected = ret
1620 1620 self._compare_ok(id_, expected, given=response.body)
1621 1621
1622 1622 def test_api_grant_user_permission_wrong_permission(self):
1623 1623 perm = 'haha.no.permission'
1624 1624 id_, params = _build_data(self.apikey,
1625 1625 'grant_user_permission',
1626 1626 repoid=self.REPO,
1627 1627 userid=TEST_USER_ADMIN_LOGIN,
1628 1628 perm=perm)
1629 1629 response = api_call(self, params)
1630 1630
1631 1631 expected = 'permission `%s` does not exist' % perm
1632 1632 self._compare_error(id_, expected, given=response.body)
1633 1633
1634 1634 @mock.patch.object(RepoModel, 'grant_user_permission', crash)
1635 1635 def test_api_grant_user_permission_exception_when_adding(self):
1636 1636 perm = 'repository.read'
1637 1637 id_, params = _build_data(self.apikey,
1638 1638 'grant_user_permission',
1639 1639 repoid=self.REPO,
1640 1640 userid=TEST_USER_ADMIN_LOGIN,
1641 1641 perm=perm)
1642 1642 response = api_call(self, params)
1643 1643
1644 1644 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
1645 1645 TEST_USER_ADMIN_LOGIN, self.REPO
1646 1646 )
1647 1647 self._compare_error(id_, expected, given=response.body)
1648 1648
1649 1649 def test_api_revoke_user_permission(self):
1650 1650 id_, params = _build_data(self.apikey,
1651 1651 'revoke_user_permission',
1652 1652 repoid=self.REPO,
1653 1653 userid=TEST_USER_ADMIN_LOGIN, )
1654 1654 response = api_call(self, params)
1655 1655
1656 1656 expected = {
1657 1657 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
1658 1658 TEST_USER_ADMIN_LOGIN, self.REPO
1659 1659 ),
1660 1660 'success': True
1661 1661 }
1662 1662 self._compare_ok(id_, expected, given=response.body)
1663 1663
1664 1664 @mock.patch.object(RepoModel, 'revoke_user_permission', crash)
1665 1665 def test_api_revoke_user_permission_exception_when_adding(self):
1666 1666 id_, params = _build_data(self.apikey,
1667 1667 'revoke_user_permission',
1668 1668 repoid=self.REPO,
1669 1669 userid=TEST_USER_ADMIN_LOGIN, )
1670 1670 response = api_call(self, params)
1671 1671
1672 1672 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
1673 1673 TEST_USER_ADMIN_LOGIN, self.REPO
1674 1674 )
1675 1675 self._compare_error(id_, expected, given=response.body)
1676 1676
1677 1677 @parameterized.expand([('none', 'repository.none'),
1678 1678 ('read', 'repository.read'),
1679 1679 ('write', 'repository.write'),
1680 1680 ('admin', 'repository.admin')])
1681 1681 def test_api_grant_user_group_permission(self, name, perm):
1682 1682 id_, params = _build_data(self.apikey,
1683 1683 'grant_user_group_permission',
1684 1684 repoid=self.REPO,
1685 1685 usergroupid=TEST_USER_GROUP,
1686 1686 perm=perm)
1687 1687 response = api_call(self, params)
1688 1688
1689 1689 ret = {
1690 1690 'msg': 'Granted perm: `%s` for user group: `%s` in repo: `%s`' % (
1691 1691 perm, TEST_USER_GROUP, self.REPO
1692 1692 ),
1693 1693 'success': True
1694 1694 }
1695 1695 expected = ret
1696 1696 self._compare_ok(id_, expected, given=response.body)
1697 1697
1698 1698 def test_api_grant_user_group_permission_wrong_permission(self):
1699 1699 perm = 'haha.no.permission'
1700 1700 id_, params = _build_data(self.apikey,
1701 1701 'grant_user_group_permission',
1702 1702 repoid=self.REPO,
1703 1703 usergroupid=TEST_USER_GROUP,
1704 1704 perm=perm)
1705 1705 response = api_call(self, params)
1706 1706
1707 1707 expected = 'permission `%s` does not exist' % perm
1708 1708 self._compare_error(id_, expected, given=response.body)
1709 1709
1710 1710 @mock.patch.object(RepoModel, 'grant_user_group_permission', crash)
1711 1711 def test_api_grant_user_group_permission_exception_when_adding(self):
1712 1712 perm = 'repository.read'
1713 1713 id_, params = _build_data(self.apikey,
1714 1714 'grant_user_group_permission',
1715 1715 repoid=self.REPO,
1716 1716 usergroupid=TEST_USER_GROUP,
1717 1717 perm=perm)
1718 1718 response = api_call(self, params)
1719 1719
1720 1720 expected = 'failed to edit permission for user group: `%s` in repo: `%s`' % (
1721 1721 TEST_USER_GROUP, self.REPO
1722 1722 )
1723 1723 self._compare_error(id_, expected, given=response.body)
1724 1724
1725 1725 def test_api_revoke_user_group_permission(self):
1726 1726 RepoModel().grant_user_group_permission(repo=self.REPO,
1727 1727 group_name=TEST_USER_GROUP,
1728 1728 perm='repository.read')
1729 1729 Session().commit()
1730 1730 id_, params = _build_data(self.apikey,
1731 1731 'revoke_user_group_permission',
1732 1732 repoid=self.REPO,
1733 1733 usergroupid=TEST_USER_GROUP, )
1734 1734 response = api_call(self, params)
1735 1735
1736 1736 expected = {
1737 1737 'msg': 'Revoked perm for user group: `%s` in repo: `%s`' % (
1738 1738 TEST_USER_GROUP, self.REPO
1739 1739 ),
1740 1740 'success': True
1741 1741 }
1742 1742 self._compare_ok(id_, expected, given=response.body)
1743 1743
1744 1744 @mock.patch.object(RepoModel, 'revoke_user_group_permission', crash)
1745 1745 def test_api_revoke_user_group_permission_exception_when_adding(self):
1746 1746 id_, params = _build_data(self.apikey,
1747 1747 'revoke_user_group_permission',
1748 1748 repoid=self.REPO,
1749 1749 usergroupid=TEST_USER_GROUP, )
1750 1750 response = api_call(self, params)
1751 1751
1752 1752 expected = 'failed to edit permission for user group: `%s` in repo: `%s`' % (
1753 1753 TEST_USER_GROUP, self.REPO
1754 1754 )
1755 1755 self._compare_error(id_, expected, given=response.body)
1756 1756
1757 1757 @parameterized.expand([
1758 1758 ('none', 'group.none', 'none'),
1759 1759 ('read', 'group.read', 'none'),
1760 1760 ('write', 'group.write', 'none'),
1761 1761 ('admin', 'group.admin', 'none'),
1762 1762
1763 1763 ('none', 'group.none', 'all'),
1764 1764 ('read', 'group.read', 'all'),
1765 1765 ('write', 'group.write', 'all'),
1766 1766 ('admin', 'group.admin', 'all'),
1767 1767
1768 1768 ('none', 'group.none', 'repos'),
1769 1769 ('read', 'group.read', 'repos'),
1770 1770 ('write', 'group.write', 'repos'),
1771 1771 ('admin', 'group.admin', 'repos'),
1772 1772
1773 1773 ('none', 'group.none', 'groups'),
1774 1774 ('read', 'group.read', 'groups'),
1775 1775 ('write', 'group.write', 'groups'),
1776 1776 ('admin', 'group.admin', 'groups'),
1777 1777 ])
1778 1778 def test_api_grant_user_permission_to_repo_group(self, name, perm, apply_to_children):
1779 1779 id_, params = _build_data(self.apikey,
1780 1780 'grant_user_permission_to_repo_group',
1781 1781 repogroupid=TEST_REPO_GROUP,
1782 1782 userid=TEST_USER_ADMIN_LOGIN,
1783 1783 perm=perm, apply_to_children=apply_to_children)
1784 1784 response = api_call(self, params)
1785 1785
1786 1786 ret = {
1787 1787 'msg': 'Granted perm: `%s` (recursive:%s) for user: `%s` in repo group: `%s`' % (
1788 1788 perm, apply_to_children, TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
1789 1789 ),
1790 1790 'success': True
1791 1791 }
1792 1792 expected = ret
1793 1793 self._compare_ok(id_, expected, given=response.body)
1794 1794
1795 1795 @parameterized.expand([
1796 1796 ('none_fails', 'group.none', 'none', False, False),
1797 1797 ('read_fails', 'group.read', 'none', False, False),
1798 1798 ('write_fails', 'group.write', 'none', False, False),
1799 1799 ('admin_fails', 'group.admin', 'none', False, False),
1800 1800
1801 1801 # with granted perms
1802 1802 ('none_ok', 'group.none', 'none', True, True),
1803 1803 ('read_ok', 'group.read', 'none', True, True),
1804 1804 ('write_ok', 'group.write', 'none', True, True),
1805 1805 ('admin_ok', 'group.admin', 'none', True, True),
1806 1806 ])
1807 1807 def test_api_grant_user_permission_to_repo_group_by_regular_user(
1808 1808 self, name, perm, apply_to_children, grant_admin, access_ok):
1809 1809 if grant_admin:
1810 1810 RepoGroupModel().grant_user_permission(TEST_REPO_GROUP,
1811 1811 self.TEST_USER_LOGIN,
1812 1812 'group.admin')
1813 1813 Session().commit()
1814 1814
1815 1815 id_, params = _build_data(self.apikey_regular,
1816 1816 'grant_user_permission_to_repo_group',
1817 1817 repogroupid=TEST_REPO_GROUP,
1818 1818 userid=TEST_USER_ADMIN_LOGIN,
1819 1819 perm=perm, apply_to_children=apply_to_children)
1820 1820 response = api_call(self, params)
1821 1821 if access_ok:
1822 1822 ret = {
1823 1823 'msg': 'Granted perm: `%s` (recursive:%s) for user: `%s` in repo group: `%s`' % (
1824 1824 perm, apply_to_children, TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
1825 1825 ),
1826 1826 'success': True
1827 1827 }
1828 1828 expected = ret
1829 1829 self._compare_ok(id_, expected, given=response.body)
1830 1830 else:
1831 1831 expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP
1832 1832 self._compare_error(id_, expected, given=response.body)
1833 1833
1834 1834 def test_api_grant_user_permission_to_repo_group_wrong_permission(self):
1835 1835 perm = 'haha.no.permission'
1836 1836 id_, params = _build_data(self.apikey,
1837 1837 'grant_user_permission_to_repo_group',
1838 1838 repogroupid=TEST_REPO_GROUP,
1839 1839 userid=TEST_USER_ADMIN_LOGIN,
1840 1840 perm=perm)
1841 1841 response = api_call(self, params)
1842 1842
1843 1843 expected = 'permission `%s` does not exist' % perm
1844 1844 self._compare_error(id_, expected, given=response.body)
1845 1845
1846 1846 @mock.patch.object(RepoGroupModel, 'grant_user_permission', crash)
1847 1847 def test_api_grant_user_permission_to_repo_group_exception_when_adding(self):
1848 1848 perm = 'group.read'
1849 1849 id_, params = _build_data(self.apikey,
1850 1850 'grant_user_permission_to_repo_group',
1851 1851 repogroupid=TEST_REPO_GROUP,
1852 1852 userid=TEST_USER_ADMIN_LOGIN,
1853 1853 perm=perm)
1854 1854 response = api_call(self, params)
1855 1855
1856 1856 expected = 'failed to edit permission for user: `%s` in repo group: `%s`' % (
1857 1857 TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
1858 1858 )
1859 1859 self._compare_error(id_, expected, given=response.body)
1860 1860
1861 1861 @parameterized.expand([
1862 1862 ('none', 'none'),
1863 1863 ('all', 'all'),
1864 1864 ('repos', 'repos'),
1865 1865 ('groups', 'groups'),
1866 1866 ])
1867 1867 def test_api_revoke_user_permission_from_repo_group(self, name, apply_to_children):
1868 1868 RepoGroupModel().grant_user_permission(repo_group=TEST_REPO_GROUP,
1869 1869 user=TEST_USER_ADMIN_LOGIN,
1870 1870 perm='group.read',)
1871 1871 Session().commit()
1872 1872
1873 1873 id_, params = _build_data(self.apikey,
1874 1874 'revoke_user_permission_from_repo_group',
1875 1875 repogroupid=TEST_REPO_GROUP,
1876 1876 userid=TEST_USER_ADMIN_LOGIN,
1877 1877 apply_to_children=apply_to_children,)
1878 1878 response = api_call(self, params)
1879 1879
1880 1880 expected = {
1881 1881 'msg': 'Revoked perm (recursive:%s) for user: `%s` in repo group: `%s`' % (
1882 1882 apply_to_children, TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
1883 1883 ),
1884 1884 'success': True
1885 1885 }
1886 1886 self._compare_ok(id_, expected, given=response.body)
1887 1887
1888 1888 @parameterized.expand([
1889 1889 ('none', 'none', False, False),
1890 1890 ('all', 'all', False, False),
1891 1891 ('repos', 'repos', False, False),
1892 1892 ('groups', 'groups', False, False),
1893 1893
1894 1894 # after granting admin rights
1895 1895 ('none', 'none', False, False),
1896 1896 ('all', 'all', False, False),
1897 1897 ('repos', 'repos', False, False),
1898 1898 ('groups', 'groups', False, False),
1899 1899 ])
1900 1900 def test_api_revoke_user_permission_from_repo_group_by_regular_user(
1901 1901 self, name, apply_to_children, grant_admin, access_ok):
1902 1902 RepoGroupModel().grant_user_permission(repo_group=TEST_REPO_GROUP,
1903 1903 user=TEST_USER_ADMIN_LOGIN,
1904 1904 perm='group.read',)
1905 1905 Session().commit()
1906 1906
1907 1907 if grant_admin:
1908 1908 RepoGroupModel().grant_user_permission(TEST_REPO_GROUP,
1909 1909 self.TEST_USER_LOGIN,
1910 1910 'group.admin')
1911 1911 Session().commit()
1912 1912
1913 1913 id_, params = _build_data(self.apikey_regular,
1914 1914 'revoke_user_permission_from_repo_group',
1915 1915 repogroupid=TEST_REPO_GROUP,
1916 1916 userid=TEST_USER_ADMIN_LOGIN,
1917 1917 apply_to_children=apply_to_children,)
1918 1918 response = api_call(self, params)
1919 1919 if access_ok:
1920 1920 expected = {
1921 1921 'msg': 'Revoked perm (recursive:%s) for user: `%s` in repo group: `%s`' % (
1922 1922 apply_to_children, TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
1923 1923 ),
1924 1924 'success': True
1925 1925 }
1926 1926 self._compare_ok(id_, expected, given=response.body)
1927 1927 else:
1928 1928 expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP
1929 1929 self._compare_error(id_, expected, given=response.body)
1930 1930
1931 1931 @mock.patch.object(RepoGroupModel, 'revoke_user_permission', crash)
1932 1932 def test_api_revoke_user_permission_from_repo_group_exception_when_adding(self):
1933 1933 id_, params = _build_data(self.apikey,
1934 1934 'revoke_user_permission_from_repo_group',
1935 1935 repogroupid=TEST_REPO_GROUP,
1936 1936 userid=TEST_USER_ADMIN_LOGIN, )
1937 1937 response = api_call(self, params)
1938 1938
1939 1939 expected = 'failed to edit permission for user: `%s` in repo group: `%s`' % (
1940 1940 TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
1941 1941 )
1942 1942 self._compare_error(id_, expected, given=response.body)
1943 1943
1944 1944 @parameterized.expand([
1945 1945 ('none', 'group.none', 'none'),
1946 1946 ('read', 'group.read', 'none'),
1947 1947 ('write', 'group.write', 'none'),
1948 1948 ('admin', 'group.admin', 'none'),
1949 1949
1950 1950 ('none', 'group.none', 'all'),
1951 1951 ('read', 'group.read', 'all'),
1952 1952 ('write', 'group.write', 'all'),
1953 1953 ('admin', 'group.admin', 'all'),
1954 1954
1955 1955 ('none', 'group.none', 'repos'),
1956 1956 ('read', 'group.read', 'repos'),
1957 1957 ('write', 'group.write', 'repos'),
1958 1958 ('admin', 'group.admin', 'repos'),
1959 1959
1960 1960 ('none', 'group.none', 'groups'),
1961 1961 ('read', 'group.read', 'groups'),
1962 1962 ('write', 'group.write', 'groups'),
1963 1963 ('admin', 'group.admin', 'groups'),
1964 1964 ])
1965 1965 def test_api_grant_user_group_permission_to_repo_group(self, name, perm, apply_to_children):
1966 1966 id_, params = _build_data(self.apikey,
1967 1967 'grant_user_group_permission_to_repo_group',
1968 1968 repogroupid=TEST_REPO_GROUP,
1969 1969 usergroupid=TEST_USER_GROUP,
1970 1970 perm=perm,
1971 1971 apply_to_children=apply_to_children,)
1972 1972 response = api_call(self, params)
1973 1973
1974 1974 ret = {
1975 1975 'msg': 'Granted perm: `%s` (recursive:%s) for user group: `%s` in repo group: `%s`' % (
1976 1976 perm, apply_to_children, TEST_USER_GROUP, TEST_REPO_GROUP
1977 1977 ),
1978 1978 'success': True
1979 1979 }
1980 1980 expected = ret
1981 1981 self._compare_ok(id_, expected, given=response.body)
1982 1982
1983 1983 @parameterized.expand([
1984 1984 ('none_fails', 'group.none', 'none', False, False),
1985 1985 ('read_fails', 'group.read', 'none', False, False),
1986 1986 ('write_fails', 'group.write', 'none', False, False),
1987 1987 ('admin_fails', 'group.admin', 'none', False, False),
1988 1988
1989 1989 # with granted perms
1990 1990 ('none_ok', 'group.none', 'none', True, True),
1991 1991 ('read_ok', 'group.read', 'none', True, True),
1992 1992 ('write_ok', 'group.write', 'none', True, True),
1993 1993 ('admin_ok', 'group.admin', 'none', True, True),
1994 1994 ])
1995 1995 def test_api_grant_user_group_permission_to_repo_group_by_regular_user(
1996 1996 self, name, perm, apply_to_children, grant_admin, access_ok):
1997 1997 if grant_admin:
1998 1998 RepoGroupModel().grant_user_permission(TEST_REPO_GROUP,
1999 1999 self.TEST_USER_LOGIN,
2000 2000 'group.admin')
2001 2001 Session().commit()
2002 2002
2003 2003 id_, params = _build_data(self.apikey_regular,
2004 2004 'grant_user_group_permission_to_repo_group',
2005 2005 repogroupid=TEST_REPO_GROUP,
2006 2006 usergroupid=TEST_USER_GROUP,
2007 2007 perm=perm,
2008 2008 apply_to_children=apply_to_children,)
2009 2009 response = api_call(self, params)
2010 2010 if access_ok:
2011 2011 ret = {
2012 2012 'msg': 'Granted perm: `%s` (recursive:%s) for user group: `%s` in repo group: `%s`' % (
2013 2013 perm, apply_to_children, TEST_USER_GROUP, TEST_REPO_GROUP
2014 2014 ),
2015 2015 'success': True
2016 2016 }
2017 2017 expected = ret
2018 2018 self._compare_ok(id_, expected, given=response.body)
2019 2019 else:
2020 2020 expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP
2021 2021 self._compare_error(id_, expected, given=response.body)
2022 2022
2023 2023 def test_api_grant_user_group_permission_to_repo_group_wrong_permission(self):
2024 2024 perm = 'haha.no.permission'
2025 2025 id_, params = _build_data(self.apikey,
2026 2026 'grant_user_group_permission_to_repo_group',
2027 2027 repogroupid=TEST_REPO_GROUP,
2028 2028 usergroupid=TEST_USER_GROUP,
2029 2029 perm=perm)
2030 2030 response = api_call(self, params)
2031 2031
2032 2032 expected = 'permission `%s` does not exist' % perm
2033 2033 self._compare_error(id_, expected, given=response.body)
2034 2034
2035 2035 @mock.patch.object(RepoGroupModel, 'grant_user_group_permission', crash)
2036 2036 def test_api_grant_user_group_permission_exception_when_adding(self):
2037 2037 perm = 'group.read'
2038 2038 id_, params = _build_data(self.apikey,
2039 2039 'grant_user_group_permission_to_repo_group',
2040 2040 repogroupid=TEST_REPO_GROUP,
2041 2041 usergroupid=TEST_USER_GROUP,
2042 2042 perm=perm)
2043 2043 response = api_call(self, params)
2044 2044
2045 2045 expected = 'failed to edit permission for user group: `%s` in repo group: `%s`' % (
2046 2046 TEST_USER_GROUP, TEST_REPO_GROUP
2047 2047 )
2048 2048 self._compare_error(id_, expected, given=response.body)
2049 2049
2050 2050 @parameterized.expand([
2051 2051 ('none', 'none'),
2052 2052 ('all', 'all'),
2053 2053 ('repos', 'repos'),
2054 2054 ('groups', 'groups'),
2055 2055 ])
2056 2056 def test_api_revoke_user_group_permission_from_repo_group(self, name, apply_to_children):
2057 2057 RepoGroupModel().grant_user_group_permission(repo_group=TEST_REPO_GROUP,
2058 2058 group_name=TEST_USER_GROUP,
2059 2059 perm='group.read',)
2060 2060 Session().commit()
2061 2061 id_, params = _build_data(self.apikey,
2062 2062 'revoke_user_group_permission_from_repo_group',
2063 2063 repogroupid=TEST_REPO_GROUP,
2064 2064 usergroupid=TEST_USER_GROUP,
2065 2065 apply_to_children=apply_to_children,)
2066 2066 response = api_call(self, params)
2067 2067
2068 2068 expected = {
2069 2069 'msg': 'Revoked perm (recursive:%s) for user group: `%s` in repo group: `%s`' % (
2070 2070 apply_to_children, TEST_USER_GROUP, TEST_REPO_GROUP
2071 2071 ),
2072 2072 'success': True
2073 2073 }
2074 2074 self._compare_ok(id_, expected, given=response.body)
2075 2075
2076 2076 @parameterized.expand([
2077 2077 ('none', 'none', False, False),
2078 2078 ('all', 'all', False, False),
2079 2079 ('repos', 'repos', False, False),
2080 2080 ('groups', 'groups', False, False),
2081 2081
2082 2082 # after granting admin rights
2083 2083 ('none', 'none', False, False),
2084 2084 ('all', 'all', False, False),
2085 2085 ('repos', 'repos', False, False),
2086 2086 ('groups', 'groups', False, False),
2087 2087 ])
2088 2088 def test_api_revoke_user_group_permission_from_repo_group_by_regular_user(
2089 2089 self, name, apply_to_children, grant_admin, access_ok):
2090 2090 RepoGroupModel().grant_user_permission(repo_group=TEST_REPO_GROUP,
2091 2091 user=TEST_USER_ADMIN_LOGIN,
2092 2092 perm='group.read',)
2093 2093 Session().commit()
2094 2094
2095 2095 if grant_admin:
2096 2096 RepoGroupModel().grant_user_permission(TEST_REPO_GROUP,
2097 2097 self.TEST_USER_LOGIN,
2098 2098 'group.admin')
2099 2099 Session().commit()
2100 2100
2101 2101 id_, params = _build_data(self.apikey_regular,
2102 2102 'revoke_user_group_permission_from_repo_group',
2103 2103 repogroupid=TEST_REPO_GROUP,
2104 2104 usergroupid=TEST_USER_GROUP,
2105 2105 apply_to_children=apply_to_children,)
2106 2106 response = api_call(self, params)
2107 2107 if access_ok:
2108 2108 expected = {
2109 2109 'msg': 'Revoked perm (recursive:%s) for user group: `%s` in repo group: `%s`' % (
2110 2110 apply_to_children, TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
2111 2111 ),
2112 2112 'success': True
2113 2113 }
2114 2114 self._compare_ok(id_, expected, given=response.body)
2115 2115 else:
2116 2116 expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP
2117 2117 self._compare_error(id_, expected, given=response.body)
2118 2118
2119 2119 @mock.patch.object(RepoGroupModel, 'revoke_user_group_permission', crash)
2120 2120 def test_api_revoke_user_group_permission_from_repo_group_exception_when_adding(self):
2121 2121 id_, params = _build_data(self.apikey, 'revoke_user_group_permission_from_repo_group',
2122 2122 repogroupid=TEST_REPO_GROUP,
2123 2123 usergroupid=TEST_USER_GROUP,)
2124 2124 response = api_call(self, params)
2125 2125
2126 2126 expected = 'failed to edit permission for user group: `%s` in repo group: `%s`' % (
2127 2127 TEST_USER_GROUP, TEST_REPO_GROUP
2128 2128 )
2129 2129 self._compare_error(id_, expected, given=response.body)
2130 2130
2131 2131 def test_api_get_gist(self):
2132 2132 gist = fixture.create_gist()
2133 2133 gist_id = gist.gist_access_id
2134 2134 gist_created_on = gist.created_on
2135 2135 id_, params = _build_data(self.apikey, 'get_gist',
2136 2136 gistid=gist_id, )
2137 2137 response = api_call(self, params)
2138 2138
2139 2139 expected = {
2140 2140 'access_id': gist_id,
2141 2141 'created_on': gist_created_on,
2142 2142 'description': 'new-gist',
2143 2143 'expires': -1.0,
2144 2144 'gist_id': int(gist_id),
2145 2145 'type': 'public',
2146 2146 'url': 'http://localhost:80/_admin/gists/%s' % gist_id
2147 2147 }
2148 2148
2149 2149 self._compare_ok(id_, expected, given=response.body)
2150 2150
2151 2151 def test_api_get_gist_that_does_not_exist(self):
2152 2152 id_, params = _build_data(self.apikey_regular, 'get_gist',
2153 2153 gistid='12345', )
2154 2154 response = api_call(self, params)
2155 2155 expected = 'gist `%s` does not exist' % ('12345',)
2156 2156 self._compare_error(id_, expected, given=response.body)
2157 2157
2158 2158 def test_api_get_gist_private_gist_without_permission(self):
2159 2159 gist = fixture.create_gist()
2160 2160 gist_id = gist.gist_access_id
2161 2161 gist_created_on = gist.created_on
2162 2162 id_, params = _build_data(self.apikey_regular, 'get_gist',
2163 2163 gistid=gist_id, )
2164 2164 response = api_call(self, params)
2165 2165
2166 2166 expected = 'gist `%s` does not exist' % gist_id
2167 2167 self._compare_error(id_, expected, given=response.body)
2168 2168
2169 2169 def test_api_get_gists(self):
2170 2170 fixture.create_gist()
2171 2171 fixture.create_gist()
2172 2172
2173 2173 id_, params = _build_data(self.apikey, 'get_gists')
2174 2174 response = api_call(self, params)
2175 2175 expected = response.json
2176 2176 self.assertEqual(len(response.json['result']), 2)
2177 2177 #self._compare_ok(id_, expected, given=response.body)
2178 2178
2179 2179 def test_api_get_gists_regular_user(self):
2180 2180 # by admin
2181 2181 fixture.create_gist()
2182 2182 fixture.create_gist()
2183 2183
2184 2184 # by reg user
2185 2185 fixture.create_gist(owner=self.TEST_USER_LOGIN)
2186 2186 fixture.create_gist(owner=self.TEST_USER_LOGIN)
2187 2187 fixture.create_gist(owner=self.TEST_USER_LOGIN)
2188 2188
2189 2189 id_, params = _build_data(self.apikey_regular, 'get_gists')
2190 2190 response = api_call(self, params)
2191 2191 expected = response.json
2192 2192 self.assertEqual(len(response.json['result']), 3)
2193 2193 #self._compare_ok(id_, expected, given=response.body)
2194 2194
2195 2195 def test_api_get_gists_only_for_regular_user(self):
2196 2196 # by admin
2197 2197 fixture.create_gist()
2198 2198 fixture.create_gist()
2199 2199
2200 2200 # by reg user
2201 2201 fixture.create_gist(owner=self.TEST_USER_LOGIN)
2202 2202 fixture.create_gist(owner=self.TEST_USER_LOGIN)
2203 2203 fixture.create_gist(owner=self.TEST_USER_LOGIN)
2204 2204
2205 2205 id_, params = _build_data(self.apikey, 'get_gists',
2206 2206 userid=self.TEST_USER_LOGIN)
2207 2207 response = api_call(self, params)
2208 2208 expected = response.json
2209 2209 self.assertEqual(len(response.json['result']), 3)
2210 2210 #self._compare_ok(id_, expected, given=response.body)
2211 2211
2212 2212 def test_api_get_gists_regular_user_with_different_userid(self):
2213 2213 id_, params = _build_data(self.apikey_regular, 'get_gists',
2214 2214 userid=TEST_USER_ADMIN_LOGIN)
2215 2215 response = api_call(self, params)
2216 2216 expected = 'userid is not the same as your user'
2217 2217 self._compare_error(id_, expected, given=response.body)
2218 2218
2219 2219 def test_api_create_gist(self):
2220 2220 id_, params = _build_data(self.apikey_regular, 'create_gist',
2221 2221 lifetime=10,
2222 2222 description='foobar-gist',
2223 2223 gist_type='public',
2224 2224 files={'foobar': {'content': 'foo'}})
2225 2225 response = api_call(self, params)
2226 2226 response_json = response.json
2227 2227 expected = {
2228 2228 'gist': {
2229 2229 'access_id': response_json['result']['gist']['access_id'],
2230 2230 'created_on': response_json['result']['gist']['created_on'],
2231 2231 'description': 'foobar-gist',
2232 2232 'expires': response_json['result']['gist']['expires'],
2233 2233 'gist_id': response_json['result']['gist']['gist_id'],
2234 2234 'type': 'public',
2235 2235 'url': response_json['result']['gist']['url']
2236 2236 },
2237 2237 'msg': 'created new gist'
2238 2238 }
2239 2239 self._compare_ok(id_, expected, given=response.body)
2240 2240
2241 2241 @mock.patch.object(GistModel, 'create', crash)
2242 2242 def test_api_create_gist_exception_occurred(self):
2243 2243 id_, params = _build_data(self.apikey_regular, 'create_gist',
2244 2244 files={})
2245 2245 response = api_call(self, params)
2246 2246 expected = 'failed to create gist'
2247 2247 self._compare_error(id_, expected, given=response.body)
2248 2248
2249 2249 def test_api_delete_gist(self):
2250 2250 gist_id = fixture.create_gist().gist_access_id
2251 2251 id_, params = _build_data(self.apikey, 'delete_gist',
2252 2252 gistid=gist_id)
2253 2253 response = api_call(self, params)
2254 2254 expected = {'gist': None, 'msg': 'deleted gist ID:%s' % gist_id}
2255 2255 self._compare_ok(id_, expected, given=response.body)
2256 2256
2257 2257 def test_api_delete_gist_regular_user(self):
2258 2258 gist_id = fixture.create_gist(owner=self.TEST_USER_LOGIN).gist_access_id
2259 2259 id_, params = _build_data(self.apikey_regular, 'delete_gist',
2260 2260 gistid=gist_id)
2261 2261 response = api_call(self, params)
2262 2262 expected = {'gist': None, 'msg': 'deleted gist ID:%s' % gist_id}
2263 2263 self._compare_ok(id_, expected, given=response.body)
2264 2264
2265 2265 def test_api_delete_gist_regular_user_no_permission(self):
2266 2266 gist_id = fixture.create_gist().gist_access_id
2267 2267 id_, params = _build_data(self.apikey_regular, 'delete_gist',
2268 2268 gistid=gist_id)
2269 2269 response = api_call(self, params)
2270 2270 expected = 'gist `%s` does not exist' % (gist_id,)
2271 2271 self._compare_error(id_, expected, given=response.body)
2272 2272
2273 2273 @mock.patch.object(GistModel, 'delete', crash)
2274 2274 def test_api_delete_gist_exception_occurred(self):
2275 2275 gist_id = fixture.create_gist().gist_access_id
2276 2276 id_, params = _build_data(self.apikey, 'delete_gist',
2277 2277 gistid=gist_id)
2278 2278 response = api_call(self, params)
2279 2279 expected = 'failed to delete gist ID:%s' % (gist_id,)
2280 2280 self._compare_error(id_, expected, given=response.body)
2281 2281
2282 2282 def test_api_get_ip(self):
2283 2283 id_, params = _build_data(self.apikey, 'get_ip')
2284 2284 response = api_call(self, params)
2285 2285 expected = {
2286 2286 'server_ip_addr': '0.0.0.0',
2287 2287 'user_ips': []
2288 2288 }
2289 2289 self._compare_ok(id_, expected, given=response.body)
2290 2290
2291 2291 def test_api_get_server_info(self):
2292 2292 id_, params = _build_data(self.apikey, 'get_server_info')
2293 2293 response = api_call(self, params)
2294 2294 expected = Setting.get_server_info()
2295 2295 self._compare_ok(id_, expected, given=response.body)
@@ -1,21 +1,21 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 from kallithea.tests import *
16 from kallithea.tests.api.api_base import BaseTestApi
16 from kallithea.tests.api.api_base import _BaseTestApi
17 17
18 18
19 class TestGitApi(BaseTestApi, TestController):
19 class TestGitApi(_BaseTestApi, TestController):
20 20 REPO = GIT_REPO
21 21 REPO_TYPE = 'git'
@@ -1,21 +1,21 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 from kallithea.tests import *
16 from kallithea.tests.api.api_base import BaseTestApi
16 from kallithea.tests.api.api_base import _BaseTestApi
17 17
18 18
19 class TestHgApi(BaseTestApi, TestController):
19 class TestHgApi(_BaseTestApi, TestController):
20 20 REPO = HG_REPO
21 21 REPO_TYPE = 'hg'
@@ -1,654 +1,654 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 import os
4 4 import mock
5 5 import urllib
6 6
7 7 from kallithea.lib import vcs
8 8 from kallithea.model.db import Repository, RepoGroup, UserRepoToPerm, User,\
9 9 Permission
10 10 from kallithea.model.user import UserModel
11 11 from kallithea.tests import *
12 12 from kallithea.model.repo_group import RepoGroupModel
13 13 from kallithea.model.repo import RepoModel
14 14 from kallithea.model.meta import Session
15 15 from kallithea.tests.fixture import Fixture, error_function
16 16
17 17 fixture = Fixture()
18 18
19 19
20 20 def _get_permission_for_user(user, repo):
21 21 perm = UserRepoToPerm.query()\
22 22 .filter(UserRepoToPerm.repository ==
23 23 Repository.get_by_repo_name(repo))\
24 24 .filter(UserRepoToPerm.user == User.get_by_username(user))\
25 25 .all()
26 26 return perm
27 27
28 28
29 class _BaseTest(TestController):
29 class _BaseTest(object):
30 30 """
31 31 Write all tests here
32 32 """
33 33 REPO = None
34 34 REPO_TYPE = None
35 35 NEW_REPO = None
36 36 OTHER_TYPE_REPO = None
37 37 OTHER_TYPE = None
38 38
39 39 @classmethod
40 40 def setup_class(cls):
41 41 pass
42 42
43 43 @classmethod
44 44 def teardown_class(cls):
45 45 pass
46 46
47 47 def test_index(self):
48 48 self.log_user()
49 49 response = self.app.get(url('repos'))
50 50
51 51 def test_create(self):
52 52 self.log_user()
53 53 repo_name = self.NEW_REPO
54 54 description = 'description for newly created repo'
55 55 response = self.app.post(url('repos'),
56 56 fixture._get_repo_create_params(repo_private=False,
57 57 repo_name=repo_name,
58 58 repo_type=self.REPO_TYPE,
59 59 repo_description=description,
60 60 _authentication_token=self.authentication_token()))
61 61 ## run the check page that triggers the flash message
62 62 response = self.app.get(url('repo_check_home', repo_name=repo_name))
63 63 self.assertEqual(response.json, {u'result': True})
64 64 self.checkSessionFlash(response,
65 65 'Created repository <a href="/%s">%s</a>'
66 66 % (repo_name, repo_name))
67 67
68 68 # test if the repo was created in the database
69 69 new_repo = Session().query(Repository)\
70 70 .filter(Repository.repo_name == repo_name).one()
71 71
72 72 self.assertEqual(new_repo.repo_name, repo_name)
73 73 self.assertEqual(new_repo.description, description)
74 74
75 75 # test if the repository is visible in the list ?
76 76 response = self.app.get(url('summary_home', repo_name=repo_name))
77 77 response.mustcontain(repo_name)
78 78 response.mustcontain(self.REPO_TYPE)
79 79
80 80 # test if the repository was created on filesystem
81 81 try:
82 82 vcs.get_repo(os.path.join(TESTS_TMP_PATH, repo_name))
83 83 except vcs.exceptions.VCSError:
84 84 self.fail('no repo %s in filesystem' % repo_name)
85 85
86 86 RepoModel().delete(repo_name)
87 87 Session().commit()
88 88
89 89 def test_create_non_ascii(self):
90 90 self.log_user()
91 91 non_ascii = "Δ…Δ™Ε‚"
92 92 repo_name = "%s%s" % (self.NEW_REPO, non_ascii)
93 93 repo_name_unicode = repo_name.decode('utf8')
94 94 description = 'description for newly created repo' + non_ascii
95 95 description_unicode = description.decode('utf8')
96 96 response = self.app.post(url('repos'),
97 97 fixture._get_repo_create_params(repo_private=False,
98 98 repo_name=repo_name,
99 99 repo_type=self.REPO_TYPE,
100 100 repo_description=description,
101 101 _authentication_token=self.authentication_token()))
102 102 ## run the check page that triggers the flash message
103 103 response = self.app.get(url('repo_check_home', repo_name=repo_name))
104 104 self.assertEqual(response.json, {u'result': True})
105 105 self.checkSessionFlash(response,
106 106 u'Created repository <a href="/%s">%s</a>'
107 107 % (urllib.quote(repo_name), repo_name_unicode))
108 108 # test if the repo was created in the database
109 109 new_repo = Session().query(Repository)\
110 110 .filter(Repository.repo_name == repo_name_unicode).one()
111 111
112 112 self.assertEqual(new_repo.repo_name, repo_name_unicode)
113 113 self.assertEqual(new_repo.description, description_unicode)
114 114
115 115 # test if the repository is visible in the list ?
116 116 response = self.app.get(url('summary_home', repo_name=repo_name))
117 117 response.mustcontain(repo_name)
118 118 response.mustcontain(self.REPO_TYPE)
119 119
120 120 # test if the repository was created on filesystem
121 121 try:
122 122 vcs.get_repo(os.path.join(TESTS_TMP_PATH, repo_name))
123 123 except vcs.exceptions.VCSError:
124 124 self.fail('no repo %s in filesystem' % repo_name)
125 125
126 126 def test_create_in_group(self):
127 127 self.log_user()
128 128
129 129 ## create GROUP
130 130 group_name = 'sometest_%s' % self.REPO_TYPE
131 131 gr = RepoGroupModel().create(group_name=group_name,
132 132 group_description='test',
133 133 owner=TEST_USER_ADMIN_LOGIN)
134 134 Session().commit()
135 135
136 136 repo_name = 'ingroup'
137 137 repo_name_full = RepoGroup.url_sep().join([group_name, repo_name])
138 138 description = 'description for newly created repo'
139 139 response = self.app.post(url('repos'),
140 140 fixture._get_repo_create_params(repo_private=False,
141 141 repo_name=repo_name,
142 142 repo_type=self.REPO_TYPE,
143 143 repo_description=description,
144 144 repo_group=gr.group_id,
145 145 _authentication_token=self.authentication_token()))
146 146 ## run the check page that triggers the flash message
147 147 response = self.app.get(url('repo_check_home', repo_name=repo_name_full))
148 148 self.assertEqual(response.json, {u'result': True})
149 149 self.checkSessionFlash(response,
150 150 'Created repository <a href="/%s">%s</a>'
151 151 % (repo_name_full, repo_name_full))
152 152 # test if the repo was created in the database
153 153 new_repo = Session().query(Repository)\
154 154 .filter(Repository.repo_name == repo_name_full).one()
155 155 new_repo_id = new_repo.repo_id
156 156
157 157 self.assertEqual(new_repo.repo_name, repo_name_full)
158 158 self.assertEqual(new_repo.description, description)
159 159
160 160 # test if the repository is visible in the list ?
161 161 response = self.app.get(url('summary_home', repo_name=repo_name_full))
162 162 response.mustcontain(repo_name_full)
163 163 response.mustcontain(self.REPO_TYPE)
164 164
165 165 inherited_perms = UserRepoToPerm.query()\
166 166 .filter(UserRepoToPerm.repository_id == new_repo_id).all()
167 167 self.assertEqual(len(inherited_perms), 1)
168 168
169 169 # test if the repository was created on filesystem
170 170 try:
171 171 vcs.get_repo(os.path.join(TESTS_TMP_PATH, repo_name_full))
172 172 except vcs.exceptions.VCSError:
173 173 RepoGroupModel().delete(group_name)
174 174 Session().commit()
175 175 self.fail('no repo %s in filesystem' % repo_name)
176 176
177 177 RepoModel().delete(repo_name_full)
178 178 RepoGroupModel().delete(group_name)
179 179 Session().commit()
180 180
181 181 def test_create_in_group_without_needed_permissions(self):
182 182 usr = self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
183 183 # avoid spurious RepoGroup DetachedInstanceError ...
184 184 authentication_token = self.authentication_token()
185 185 # revoke
186 186 user_model = UserModel()
187 187 # disable fork and create on default user
188 188 user_model.revoke_perm(User.DEFAULT_USER, 'hg.create.repository')
189 189 user_model.grant_perm(User.DEFAULT_USER, 'hg.create.none')
190 190 user_model.revoke_perm(User.DEFAULT_USER, 'hg.fork.repository')
191 191 user_model.grant_perm(User.DEFAULT_USER, 'hg.fork.none')
192 192
193 193 # disable on regular user
194 194 user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.repository')
195 195 user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.none')
196 196 user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.repository')
197 197 user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.none')
198 198 Session().commit()
199 199
200 200 ## create GROUP
201 201 group_name = 'reg_sometest_%s' % self.REPO_TYPE
202 202 gr = RepoGroupModel().create(group_name=group_name,
203 203 group_description='test',
204 204 owner=TEST_USER_ADMIN_LOGIN)
205 205 Session().commit()
206 206
207 207 group_name_allowed = 'reg_sometest_allowed_%s' % self.REPO_TYPE
208 208 gr_allowed = RepoGroupModel().create(group_name=group_name_allowed,
209 209 group_description='test',
210 210 owner=TEST_USER_REGULAR_LOGIN)
211 211 Session().commit()
212 212
213 213 repo_name = 'ingroup'
214 214 repo_name_full = RepoGroup.url_sep().join([group_name, repo_name])
215 215 description = 'description for newly created repo'
216 216 response = self.app.post(url('repos'),
217 217 fixture._get_repo_create_params(repo_private=False,
218 218 repo_name=repo_name,
219 219 repo_type=self.REPO_TYPE,
220 220 repo_description=description,
221 221 repo_group=gr.group_id,
222 222 _authentication_token=authentication_token))
223 223
224 224 response.mustcontain('Invalid value')
225 225
226 226 # user is allowed to create in this group
227 227 repo_name = 'ingroup'
228 228 repo_name_full = RepoGroup.url_sep().join([group_name_allowed, repo_name])
229 229 description = 'description for newly created repo'
230 230 response = self.app.post(url('repos'),
231 231 fixture._get_repo_create_params(repo_private=False,
232 232 repo_name=repo_name,
233 233 repo_type=self.REPO_TYPE,
234 234 repo_description=description,
235 235 repo_group=gr_allowed.group_id,
236 236 _authentication_token=authentication_token))
237 237
238 238 ## run the check page that triggers the flash message
239 239 response = self.app.get(url('repo_check_home', repo_name=repo_name_full))
240 240 self.assertEqual(response.json, {u'result': True})
241 241 self.checkSessionFlash(response,
242 242 'Created repository <a href="/%s">%s</a>'
243 243 % (repo_name_full, repo_name_full))
244 244 # test if the repo was created in the database
245 245 new_repo = Session().query(Repository)\
246 246 .filter(Repository.repo_name == repo_name_full).one()
247 247 new_repo_id = new_repo.repo_id
248 248
249 249 self.assertEqual(new_repo.repo_name, repo_name_full)
250 250 self.assertEqual(new_repo.description, description)
251 251
252 252 # test if the repository is visible in the list ?
253 253 response = self.app.get(url('summary_home', repo_name=repo_name_full))
254 254 response.mustcontain(repo_name_full)
255 255 response.mustcontain(self.REPO_TYPE)
256 256
257 257 inherited_perms = UserRepoToPerm.query()\
258 258 .filter(UserRepoToPerm.repository_id == new_repo_id).all()
259 259 self.assertEqual(len(inherited_perms), 1)
260 260
261 261 # test if the repository was created on filesystem
262 262 try:
263 263 vcs.get_repo(os.path.join(TESTS_TMP_PATH, repo_name_full))
264 264 except vcs.exceptions.VCSError:
265 265 RepoGroupModel().delete(group_name)
266 266 Session().commit()
267 267 self.fail('no repo %s in filesystem' % repo_name)
268 268
269 269 RepoModel().delete(repo_name_full)
270 270 RepoGroupModel().delete(group_name)
271 271 RepoGroupModel().delete(group_name_allowed)
272 272 Session().commit()
273 273
274 274 def test_create_in_group_inherit_permissions(self):
275 275 self.log_user()
276 276
277 277 ## create GROUP
278 278 group_name = 'sometest_%s' % self.REPO_TYPE
279 279 gr = RepoGroupModel().create(group_name=group_name,
280 280 group_description='test',
281 281 owner=TEST_USER_ADMIN_LOGIN)
282 282 perm = Permission.get_by_key('repository.write')
283 283 RepoGroupModel().grant_user_permission(gr, TEST_USER_REGULAR_LOGIN, perm)
284 284
285 285 ## add repo permissions
286 286 Session().commit()
287 287
288 288 repo_name = 'ingroup_inherited_%s' % self.REPO_TYPE
289 289 repo_name_full = RepoGroup.url_sep().join([group_name, repo_name])
290 290 description = 'description for newly created repo'
291 291 response = self.app.post(url('repos'),
292 292 fixture._get_repo_create_params(repo_private=False,
293 293 repo_name=repo_name,
294 294 repo_type=self.REPO_TYPE,
295 295 repo_description=description,
296 296 repo_group=gr.group_id,
297 297 repo_copy_permissions=True,
298 298 _authentication_token=self.authentication_token()))
299 299
300 300 ## run the check page that triggers the flash message
301 301 response = self.app.get(url('repo_check_home', repo_name=repo_name_full))
302 302 self.checkSessionFlash(response,
303 303 'Created repository <a href="/%s">%s</a>'
304 304 % (repo_name_full, repo_name_full))
305 305 # test if the repo was created in the database
306 306 new_repo = Session().query(Repository)\
307 307 .filter(Repository.repo_name == repo_name_full).one()
308 308 new_repo_id = new_repo.repo_id
309 309
310 310 self.assertEqual(new_repo.repo_name, repo_name_full)
311 311 self.assertEqual(new_repo.description, description)
312 312
313 313 # test if the repository is visible in the list ?
314 314 response = self.app.get(url('summary_home', repo_name=repo_name_full))
315 315 response.mustcontain(repo_name_full)
316 316 response.mustcontain(self.REPO_TYPE)
317 317
318 318 # test if the repository was created on filesystem
319 319 try:
320 320 vcs.get_repo(os.path.join(TESTS_TMP_PATH, repo_name_full))
321 321 except vcs.exceptions.VCSError:
322 322 RepoGroupModel().delete(group_name)
323 323 Session().commit()
324 324 self.fail('no repo %s in filesystem' % repo_name)
325 325
326 326 #check if inherited permissiona are applied
327 327 inherited_perms = UserRepoToPerm.query()\
328 328 .filter(UserRepoToPerm.repository_id == new_repo_id).all()
329 329 self.assertEqual(len(inherited_perms), 2)
330 330
331 331 self.assertTrue(TEST_USER_REGULAR_LOGIN in [x.user.username
332 332 for x in inherited_perms])
333 333 self.assertTrue('repository.write' in [x.permission.permission_name
334 334 for x in inherited_perms])
335 335
336 336 RepoModel().delete(repo_name_full)
337 337 RepoGroupModel().delete(group_name)
338 338 Session().commit()
339 339
340 340 def test_create_remote_repo_wrong_clone_uri(self):
341 341 self.log_user()
342 342 repo_name = self.NEW_REPO
343 343 description = 'description for newly created repo'
344 344 response = self.app.post(url('repos'),
345 345 fixture._get_repo_create_params(repo_private=False,
346 346 repo_name=repo_name,
347 347 repo_type=self.REPO_TYPE,
348 348 repo_description=description,
349 349 clone_uri='http://127.0.0.1/repo',
350 350 _authentication_token=self.authentication_token()))
351 351 response.mustcontain('invalid clone URL')
352 352
353 353
354 354 def test_create_remote_repo_wrong_clone_uri_hg_svn(self):
355 355 self.log_user()
356 356 repo_name = self.NEW_REPO
357 357 description = 'description for newly created repo'
358 358 response = self.app.post(url('repos'),
359 359 fixture._get_repo_create_params(repo_private=False,
360 360 repo_name=repo_name,
361 361 repo_type=self.REPO_TYPE,
362 362 repo_description=description,
363 363 clone_uri='svn+http://127.0.0.1/repo',
364 364 _authentication_token=self.authentication_token()))
365 365 response.mustcontain('invalid clone URL')
366 366
367 367
368 368 def test_delete(self):
369 369 self.log_user()
370 370 repo_name = 'vcs_test_new_to_delete_%s' % self.REPO_TYPE
371 371 description = 'description for newly created repo'
372 372 response = self.app.post(url('repos'),
373 373 fixture._get_repo_create_params(repo_private=False,
374 374 repo_type=self.REPO_TYPE,
375 375 repo_name=repo_name,
376 376 repo_description=description,
377 377 _authentication_token=self.authentication_token()))
378 378 ## run the check page that triggers the flash message
379 379 response = self.app.get(url('repo_check_home', repo_name=repo_name))
380 380 self.checkSessionFlash(response,
381 381 'Created repository <a href="/%s">%s</a>'
382 382 % (repo_name, repo_name))
383 383 # test if the repo was created in the database
384 384 new_repo = Session().query(Repository)\
385 385 .filter(Repository.repo_name == repo_name).one()
386 386
387 387 self.assertEqual(new_repo.repo_name, repo_name)
388 388 self.assertEqual(new_repo.description, description)
389 389
390 390 # test if the repository is visible in the list ?
391 391 response = self.app.get(url('summary_home', repo_name=repo_name))
392 392 response.mustcontain(repo_name)
393 393 response.mustcontain(self.REPO_TYPE)
394 394
395 395 # test if the repository was created on filesystem
396 396 try:
397 397 vcs.get_repo(os.path.join(TESTS_TMP_PATH, repo_name))
398 398 except vcs.exceptions.VCSError:
399 399 self.fail('no repo %s in filesystem' % repo_name)
400 400
401 401 response = self.app.delete(url('repo', repo_name=repo_name))
402 402
403 403 self.checkSessionFlash(response, 'Deleted repository %s' % (repo_name))
404 404
405 405 response.follow()
406 406
407 407 #check if repo was deleted from db
408 408 deleted_repo = Session().query(Repository)\
409 409 .filter(Repository.repo_name == repo_name).scalar()
410 410
411 411 self.assertEqual(deleted_repo, None)
412 412
413 413 self.assertEqual(os.path.isdir(os.path.join(TESTS_TMP_PATH, repo_name)),
414 414 False)
415 415
416 416 def test_delete_non_ascii(self):
417 417 self.log_user()
418 418 non_ascii = "Δ…Δ™Ε‚"
419 419 repo_name = "%s%s" % (self.NEW_REPO, non_ascii)
420 420 repo_name_unicode = repo_name.decode('utf8')
421 421 description = 'description for newly created repo' + non_ascii
422 422 description_unicode = description.decode('utf8')
423 423 response = self.app.post(url('repos'),
424 424 fixture._get_repo_create_params(repo_private=False,
425 425 repo_name=repo_name,
426 426 repo_type=self.REPO_TYPE,
427 427 repo_description=description,
428 428 _authentication_token=self.authentication_token()))
429 429 ## run the check page that triggers the flash message
430 430 response = self.app.get(url('repo_check_home', repo_name=repo_name))
431 431 self.assertEqual(response.json, {u'result': True})
432 432 self.checkSessionFlash(response,
433 433 u'Created repository <a href="/%s">%s</a>'
434 434 % (urllib.quote(repo_name), repo_name_unicode))
435 435 # test if the repo was created in the database
436 436 new_repo = Session().query(Repository)\
437 437 .filter(Repository.repo_name == repo_name_unicode).one()
438 438
439 439 self.assertEqual(new_repo.repo_name, repo_name_unicode)
440 440 self.assertEqual(new_repo.description, description_unicode)
441 441
442 442 # test if the repository is visible in the list ?
443 443 response = self.app.get(url('summary_home', repo_name=repo_name))
444 444 response.mustcontain(repo_name)
445 445 response.mustcontain(self.REPO_TYPE)
446 446
447 447 # test if the repository was created on filesystem
448 448 try:
449 449 vcs.get_repo(os.path.join(TESTS_TMP_PATH, repo_name))
450 450 except vcs.exceptions.VCSError:
451 451 self.fail('no repo %s in filesystem' % repo_name)
452 452
453 453 response = self.app.delete(url('repo', repo_name=repo_name))
454 454 self.checkSessionFlash(response, 'Deleted repository %s' % (repo_name_unicode))
455 455 response.follow()
456 456
457 457 #check if repo was deleted from db
458 458 deleted_repo = Session().query(Repository)\
459 459 .filter(Repository.repo_name == repo_name_unicode).scalar()
460 460
461 461 self.assertEqual(deleted_repo, None)
462 462
463 463 self.assertEqual(os.path.isdir(os.path.join(TESTS_TMP_PATH, repo_name)),
464 464 False)
465 465
466 466 def test_delete_repo_with_group(self):
467 467 #TODO:
468 468 pass
469 469
470 470 def test_delete_browser_fakeout(self):
471 471 response = self.app.post(url('repo', repo_name=self.REPO),
472 472 params=dict(_method='delete', _authentication_token=self.authentication_token()))
473 473
474 474 def test_show(self):
475 475 self.log_user()
476 476 response = self.app.get(url('repo', repo_name=self.REPO))
477 477
478 478 def test_edit(self):
479 479 response = self.app.get(url('edit_repo', repo_name=self.REPO))
480 480
481 481 def test_set_private_flag_sets_default_to_none(self):
482 482 self.log_user()
483 483 #initially repository perm should be read
484 484 perm = _get_permission_for_user(user='default', repo=self.REPO)
485 485 self.assertTrue(len(perm), 1)
486 486 self.assertEqual(perm[0].permission.permission_name, 'repository.read')
487 487 self.assertEqual(Repository.get_by_repo_name(self.REPO).private, False)
488 488
489 489 response = self.app.put(url('repo', repo_name=self.REPO),
490 490 fixture._get_repo_create_params(repo_private=1,
491 491 repo_name=self.REPO,
492 492 repo_type=self.REPO_TYPE,
493 493 user=TEST_USER_ADMIN_LOGIN,
494 494 _authentication_token=self.authentication_token()))
495 495 self.checkSessionFlash(response,
496 496 msg='Repository %s updated successfully' % (self.REPO))
497 497 self.assertEqual(Repository.get_by_repo_name(self.REPO).private, True)
498 498
499 499 #now the repo default permission should be None
500 500 perm = _get_permission_for_user(user='default', repo=self.REPO)
501 501 self.assertTrue(len(perm), 1)
502 502 self.assertEqual(perm[0].permission.permission_name, 'repository.none')
503 503
504 504 response = self.app.put(url('repo', repo_name=self.REPO),
505 505 fixture._get_repo_create_params(repo_private=False,
506 506 repo_name=self.REPO,
507 507 repo_type=self.REPO_TYPE,
508 508 user=TEST_USER_ADMIN_LOGIN,
509 509 _authentication_token=self.authentication_token()))
510 510 self.checkSessionFlash(response,
511 511 msg='Repository %s updated successfully' % (self.REPO))
512 512 self.assertEqual(Repository.get_by_repo_name(self.REPO).private, False)
513 513
514 514 #we turn off private now the repo default permission should stay None
515 515 perm = _get_permission_for_user(user='default', repo=self.REPO)
516 516 self.assertTrue(len(perm), 1)
517 517 self.assertEqual(perm[0].permission.permission_name, 'repository.none')
518 518
519 519 #update this permission back
520 520 perm[0].permission = Permission.get_by_key('repository.read')
521 521 Session().add(perm[0])
522 522 Session().commit()
523 523
524 524 def test_set_repo_fork_has_no_self_id(self):
525 525 self.log_user()
526 526 repo = Repository.get_by_repo_name(self.REPO)
527 527 response = self.app.get(url('edit_repo_advanced', repo_name=self.REPO))
528 528 opt = """<option value="%s">vcs_test_git</option>""" % repo.repo_id
529 529 response.mustcontain(no=[opt])
530 530
531 531 def test_set_fork_of_other_repo(self):
532 532 self.log_user()
533 533 other_repo = 'other_%s' % self.REPO_TYPE
534 534 fixture.create_repo(other_repo, repo_type=self.REPO_TYPE)
535 535 repo = Repository.get_by_repo_name(self.REPO)
536 536 repo2 = Repository.get_by_repo_name(other_repo)
537 537 response = self.app.put(url('edit_repo_advanced_fork', repo_name=self.REPO),
538 538 params=dict(id_fork_of=repo2.repo_id, _authentication_token=self.authentication_token()))
539 539 repo = Repository.get_by_repo_name(self.REPO)
540 540 repo2 = Repository.get_by_repo_name(other_repo)
541 541 self.checkSessionFlash(response,
542 542 'Marked repo %s as fork of %s' % (repo.repo_name, repo2.repo_name))
543 543
544 544 assert repo.fork == repo2
545 545 response = response.follow()
546 546 # check if given repo is selected
547 547
548 548 opt = """<option value="%s" selected="selected">%s</option>""" % (
549 549 repo2.repo_id, repo2.repo_name)
550 550 response.mustcontain(opt)
551 551
552 552 fixture.destroy_repo(other_repo, forks='detach')
553 553
554 554 def test_set_fork_of_other_type_repo(self):
555 555 self.log_user()
556 556 repo = Repository.get_by_repo_name(self.REPO)
557 557 repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO)
558 558 response = self.app.put(url('edit_repo_advanced_fork', repo_name=self.REPO),
559 559 params=dict(id_fork_of=repo2.repo_id, _authentication_token=self.authentication_token()))
560 560 repo = Repository.get_by_repo_name(self.REPO)
561 561 repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO)
562 562 self.checkSessionFlash(response,
563 563 'Cannot set repository as fork of repository with other type')
564 564
565 565 def test_set_fork_of_none(self):
566 566 self.log_user()
567 567 ## mark it as None
568 568 response = self.app.put(url('edit_repo_advanced_fork', repo_name=self.REPO),
569 569 params=dict(id_fork_of=None, _authentication_token=self.authentication_token()))
570 570 repo = Repository.get_by_repo_name(self.REPO)
571 571 repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO)
572 572 self.checkSessionFlash(response,
573 573 'Marked repo %s as fork of %s'
574 574 % (repo.repo_name, "Nothing"))
575 575 assert repo.fork is None
576 576
577 577 def test_set_fork_of_same_repo(self):
578 578 self.log_user()
579 579 repo = Repository.get_by_repo_name(self.REPO)
580 580 response = self.app.put(url('edit_repo_advanced_fork', repo_name=self.REPO),
581 581 params=dict(id_fork_of=repo.repo_id, _authentication_token=self.authentication_token()))
582 582 self.checkSessionFlash(response,
583 583 'An error occurred during this operation')
584 584
585 585 def test_create_on_top_level_without_permissions(self):
586 586 usr = self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
587 587 # revoke
588 588 user_model = UserModel()
589 589 # disable fork and create on default user
590 590 user_model.revoke_perm(User.DEFAULT_USER, 'hg.create.repository')
591 591 user_model.grant_perm(User.DEFAULT_USER, 'hg.create.none')
592 592 user_model.revoke_perm(User.DEFAULT_USER, 'hg.fork.repository')
593 593 user_model.grant_perm(User.DEFAULT_USER, 'hg.fork.none')
594 594
595 595 # disable on regular user
596 596 user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.repository')
597 597 user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.none')
598 598 user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.repository')
599 599 user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.none')
600 600 Session().commit()
601 601
602 602
603 603 user = User.get(usr['user_id'])
604 604
605 605 repo_name = self.NEW_REPO+'no_perms'
606 606 description = 'description for newly created repo'
607 607 response = self.app.post(url('repos'),
608 608 fixture._get_repo_create_params(repo_private=False,
609 609 repo_name=repo_name,
610 610 repo_type=self.REPO_TYPE,
611 611 repo_description=description,
612 612 _authentication_token=self.authentication_token()))
613 613
614 614 response.mustcontain('no permission to create repository in root location')
615 615
616 616 RepoModel().delete(repo_name)
617 617 Session().commit()
618 618
619 619 @mock.patch.object(RepoModel, '_create_filesystem_repo', error_function)
620 620 def test_create_repo_when_filesystem_op_fails(self):
621 621 self.log_user()
622 622 repo_name = self.NEW_REPO
623 623 description = 'description for newly created repo'
624 624
625 625 response = self.app.post(url('repos'),
626 626 fixture._get_repo_create_params(repo_private=False,
627 627 repo_name=repo_name,
628 628 repo_type=self.REPO_TYPE,
629 629 repo_description=description,
630 630 _authentication_token=self.authentication_token()))
631 631
632 632 self.checkSessionFlash(response,
633 633 'Error creating repository %s' % repo_name)
634 634 # repo must not be in db
635 635 repo = Repository.get_by_repo_name(repo_name)
636 636 self.assertEqual(repo, None)
637 637
638 638 # repo must not be in filesystem !
639 639 self.assertFalse(os.path.isdir(os.path.join(TESTS_TMP_PATH, repo_name)))
640 640
641 class TestAdminReposControllerGIT(_BaseTest):
641 class TestAdminReposControllerGIT(TestController, _BaseTest):
642 642 REPO = GIT_REPO
643 643 REPO_TYPE = 'git'
644 644 NEW_REPO = NEW_GIT_REPO
645 645 OTHER_TYPE_REPO = HG_REPO
646 646 OTHER_TYPE = 'hg'
647 647
648 648
649 class TestAdminReposControllerHG(_BaseTest):
649 class TestAdminReposControllerHG(TestController, _BaseTest):
650 650 REPO = HG_REPO
651 651 REPO_TYPE = 'hg'
652 652 NEW_REPO = NEW_HG_REPO
653 653 OTHER_TYPE_REPO = GIT_REPO
654 654 OTHER_TYPE = 'git'
@@ -1,232 +1,237 b''
1 1 # -*- coding: utf-8 -*-
2
3 import unittest
4
2 5 from kallithea.tests import *
3 6 from kallithea.tests.fixture import Fixture
4 7
5 8 from kallithea.model.db import Repository
6 9 from kallithea.model.repo import RepoModel
7 10 from kallithea.model.user import UserModel
8 11 from kallithea.model.meta import Session
9 12
10 13 fixture = Fixture()
11 14
12 15 from kallithea.tests import *
13 16
14 17
15 class _BaseTest(TestController):
16 """
17 Write all tests here
18 """
19 REPO = None
20 REPO_TYPE = None
21 NEW_REPO = None
22 REPO_FORK = None
23
18 class _BaseFixture(unittest.TestCase):
24 19 @classmethod
25 20 def setup_class(cls):
26 21 pass
27 22
28 23 @classmethod
29 24 def teardown_class(cls):
30 25 pass
31 26
32 27 def setUp(self):
33 28 self.username = u'forkuser'
34 29 self.password = u'qweqwe'
35 30 self.u1 = fixture.create_user(self.username, password=self.password,
36 31 email=u'fork_king@example.com')
37 32 Session().commit()
38 33
39 34 def tearDown(self):
40 35 Session().delete(self.u1)
41 36 Session().commit()
42 37
38
39 class _BaseTestCase(object):
40 """
41 Write all tests here
42 """
43 REPO = None
44 REPO_TYPE = None
45 NEW_REPO = None
46 REPO_FORK = None
47
43 48 def test_index(self):
44 49 self.log_user()
45 50 repo_name = self.REPO
46 51 response = self.app.get(url(controller='forks', action='forks',
47 52 repo_name=repo_name))
48 53
49 54 response.mustcontain("""There are no forks yet""")
50 55
51 56 def test_no_permissions_to_fork(self):
52 57 usr = self.log_user(TEST_USER_REGULAR_LOGIN,
53 58 TEST_USER_REGULAR_PASS)['user_id']
54 59 user_model = UserModel()
55 60 user_model.revoke_perm(usr, 'hg.fork.repository')
56 61 user_model.grant_perm(usr, 'hg.fork.none')
57 62 u = UserModel().get(usr)
58 63 u.inherit_default_permissions = False
59 64 Session().commit()
60 65 # try create a fork
61 66 repo_name = self.REPO
62 67 self.app.post(url(controller='forks', action='fork_create',
63 68 repo_name=repo_name), {'_authentication_token': self.authentication_token()}, status=403)
64 69
65 70 def test_index_with_fork(self):
66 71 self.log_user()
67 72
68 73 # create a fork
69 74 fork_name = self.REPO_FORK
70 75 description = 'fork of vcs test'
71 76 repo_name = self.REPO
72 77 org_repo = Repository.get_by_repo_name(repo_name)
73 78 creation_args = {
74 79 'repo_name': fork_name,
75 80 'repo_group': '',
76 81 'fork_parent_id': org_repo.repo_id,
77 82 'repo_type': self.REPO_TYPE,
78 83 'description': description,
79 84 'private': 'False',
80 85 'landing_rev': 'rev:tip',
81 86 '_authentication_token': self.authentication_token()}
82 87
83 88 self.app.post(url(controller='forks', action='fork_create',
84 89 repo_name=repo_name), creation_args)
85 90
86 91 response = self.app.get(url(controller='forks', action='forks',
87 92 repo_name=repo_name))
88 93
89 94 response.mustcontain(
90 95 """<a href="/%s">%s</a>""" % (fork_name, fork_name)
91 96 )
92 97
93 98 # remove this fork
94 99 response = self.app.delete(url('repo', repo_name=fork_name))
95 100
96 101 def test_fork_create_into_group(self):
97 102 self.log_user()
98 103 group = fixture.create_repo_group('vc')
99 104 group_id = group.group_id
100 105 fork_name = self.REPO_FORK
101 106 fork_name_full = 'vc/%s' % fork_name
102 107 description = 'fork of vcs test'
103 108 repo_name = self.REPO
104 109 org_repo = Repository.get_by_repo_name(repo_name)
105 110 creation_args = {
106 111 'repo_name': fork_name,
107 112 'repo_group': group_id,
108 113 'fork_parent_id': org_repo.repo_id,
109 114 'repo_type': self.REPO_TYPE,
110 115 'description': description,
111 116 'private': 'False',
112 117 'landing_rev': 'rev:tip',
113 118 '_authentication_token': self.authentication_token()}
114 119 self.app.post(url(controller='forks', action='fork_create',
115 120 repo_name=repo_name), creation_args)
116 121 repo = Repository.get_by_repo_name(fork_name_full)
117 122 assert repo.fork.repo_name == self.REPO
118 123
119 124 ## run the check page that triggers the flash message
120 125 response = self.app.get(url('repo_check_home', repo_name=fork_name_full))
121 126 #test if we have a message that fork is ok
122 127 self.checkSessionFlash(response,
123 128 'Forked repository %s as <a href="/%s">%s</a>'
124 129 % (repo_name, fork_name_full, fork_name_full))
125 130
126 131 #test if the fork was created in the database
127 132 fork_repo = Session().query(Repository)\
128 133 .filter(Repository.repo_name == fork_name_full).one()
129 134
130 135 self.assertEqual(fork_repo.repo_name, fork_name_full)
131 136 self.assertEqual(fork_repo.fork.repo_name, repo_name)
132 137
133 138 # test if the repository is visible in the list ?
134 139 response = self.app.get(url('summary_home', repo_name=fork_name_full))
135 140 response.mustcontain(fork_name_full)
136 141 response.mustcontain(self.REPO_TYPE)
137 142 response.mustcontain('Fork of "<a href="/%s">%s</a>"' % (repo_name, repo_name))
138 143
139 144 fixture.destroy_repo(fork_name_full)
140 145 fixture.destroy_repo_group(group_id)
141 146
142 147 def test_z_fork_create(self):
143 148 self.log_user()
144 149 fork_name = self.REPO_FORK
145 150 description = 'fork of vcs test'
146 151 repo_name = self.REPO
147 152 org_repo = Repository.get_by_repo_name(repo_name)
148 153 creation_args = {
149 154 'repo_name': fork_name,
150 155 'repo_group': '',
151 156 'fork_parent_id': org_repo.repo_id,
152 157 'repo_type': self.REPO_TYPE,
153 158 'description': description,
154 159 'private': 'False',
155 160 'landing_rev': 'rev:tip',
156 161 '_authentication_token': self.authentication_token()}
157 162 self.app.post(url(controller='forks', action='fork_create',
158 163 repo_name=repo_name), creation_args)
159 164 repo = Repository.get_by_repo_name(self.REPO_FORK)
160 165 assert repo.fork.repo_name == self.REPO
161 166
162 167 ## run the check page that triggers the flash message
163 168 response = self.app.get(url('repo_check_home', repo_name=fork_name))
164 169 #test if we have a message that fork is ok
165 170 self.checkSessionFlash(response,
166 171 'Forked repository %s as <a href="/%s">%s</a>'
167 172 % (repo_name, fork_name, fork_name))
168 173
169 174 #test if the fork was created in the database
170 175 fork_repo = Session().query(Repository)\
171 176 .filter(Repository.repo_name == fork_name).one()
172 177
173 178 self.assertEqual(fork_repo.repo_name, fork_name)
174 179 self.assertEqual(fork_repo.fork.repo_name, repo_name)
175 180
176 181 # test if the repository is visible in the list ?
177 182 response = self.app.get(url('summary_home', repo_name=fork_name))
178 183 response.mustcontain(fork_name)
179 184 response.mustcontain(self.REPO_TYPE)
180 185 response.mustcontain('Fork of "<a href="/%s">%s</a>"' % (repo_name, repo_name))
181 186
182 187 def test_zz_fork_permission_page(self):
183 188 usr = self.log_user(self.username, self.password)['user_id']
184 189 repo_name = self.REPO
185 190
186 191 forks = Repository.query()\
187 192 .filter(Repository.repo_type == self.REPO_TYPE)\
188 193 .filter(Repository.fork_id != None).all()
189 194 self.assertEqual(1, len(forks))
190 195
191 196 # set read permissions for this
192 197 RepoModel().grant_user_permission(repo=forks[0],
193 198 user=usr,
194 199 perm='repository.read')
195 200 Session().commit()
196 201
197 202 response = self.app.get(url(controller='forks', action='forks',
198 203 repo_name=repo_name))
199 204
200 205 response.mustcontain('<div style="padding:5px 3px 3px 42px;">fork of vcs test</div>')
201 206
202 207 def test_zzz_fork_permission_page(self):
203 208 usr = self.log_user(self.username, self.password)['user_id']
204 209 repo_name = self.REPO
205 210
206 211 forks = Repository.query()\
207 212 .filter(Repository.repo_type == self.REPO_TYPE)\
208 213 .filter(Repository.fork_id != None).all()
209 214 self.assertEqual(1, len(forks))
210 215
211 216 # set none
212 217 RepoModel().grant_user_permission(repo=forks[0],
213 218 user=usr, perm='repository.none')
214 219 Session().commit()
215 220 # fork shouldn't be there
216 221 response = self.app.get(url(controller='forks', action='forks',
217 222 repo_name=repo_name))
218 223 response.mustcontain('There are no forks yet')
219 224
220 225
221 class TestGIT(_BaseTest):
226 class TestGIT(TestController, _BaseTestCase, _BaseFixture):
222 227 REPO = GIT_REPO
223 228 NEW_REPO = NEW_GIT_REPO
224 229 REPO_TYPE = 'git'
225 230 REPO_FORK = GIT_FORK
226 231
227 232
228 class TestHG(_BaseTest):
233 class TestHG(TestController, _BaseTestCase, _BaseFixture):
229 234 REPO = HG_REPO
230 235 NEW_REPO = NEW_HG_REPO
231 236 REPO_TYPE = 'hg'
232 237 REPO_FORK = HG_FORK
@@ -1,111 +1,111 b''
1 1 """
2 2 Module providing backend independent mixin class. It requires that
3 3 InMemoryChangeset class is working properly at backend class.
4 4 """
5 5 import os
6 6 import time
7 7 import shutil
8 8 import datetime
9 9 from kallithea.tests.vcs.conf import SCM_TESTS, get_new_dir
10 10
11 11 from kallithea.lib import vcs
12 12 from kallithea.lib.vcs.utils.compat import unittest
13 13 from kallithea.lib.vcs.nodes import FileNode
14 14
15 15
16 class BackendTestMixin(object):
16 class _BackendTestMixin(object):
17 17 """
18 18 This is a backend independent test case class which should be created
19 19 with ``type`` method.
20 20
21 21 It is required to set following attributes at subclass:
22 22
23 23 - ``backend_alias``: alias of used backend (see ``vcs.BACKENDS``)
24 24 - ``repo_path``: path to the repository which would be created for set of
25 25 tests
26 26 - ``recreate_repo_per_test``: If set to ``False``, repo would NOT be created
27 27 before every single test. Defaults to ``True``.
28 28 """
29 29 recreate_repo_per_test = True
30 30
31 31 @classmethod
32 32 def get_backend(cls):
33 33 return vcs.get_backend(cls.backend_alias)
34 34
35 35 @classmethod
36 36 def _get_commits(cls):
37 37 commits = [
38 38 {
39 39 'message': u'Initial commit',
40 40 'author': u'Joe Doe <joe.doe@example.com>',
41 41 'date': datetime.datetime(2010, 1, 1, 20),
42 42 'added': [
43 43 FileNode('foobar', content='Foobar'),
44 44 FileNode('foobar2', content='Foobar II'),
45 45 FileNode('foo/bar/baz', content='baz here!'),
46 46 ],
47 47 },
48 48 {
49 49 'message': u'Changes...',
50 50 'author': u'Jane Doe <jane.doe@example.com>',
51 51 'date': datetime.datetime(2010, 1, 1, 21),
52 52 'added': [
53 53 FileNode('some/new.txt', content='news...'),
54 54 ],
55 55 'changed': [
56 56 FileNode('foobar', 'Foobar I'),
57 57 ],
58 58 'removed': [],
59 59 },
60 60 ]
61 61 return commits
62 62
63 63 @classmethod
64 64 def setUpClass(cls):
65 65 Backend = cls.get_backend()
66 66 cls.backend_class = Backend
67 67 cls.repo_path = get_new_dir(str(time.time()))
68 68 cls.repo = Backend(cls.repo_path, create=True)
69 69 cls.imc = cls.repo.in_memory_changeset
70 70 cls.default_branch = cls.repo.DEFAULT_BRANCH_NAME
71 71
72 72 for commit in cls._get_commits():
73 73 for node in commit.get('added', []):
74 74 cls.imc.add(FileNode(node.path, content=node.content))
75 75 for node in commit.get('changed', []):
76 76 cls.imc.change(FileNode(node.path, content=node.content))
77 77 for node in commit.get('removed', []):
78 78 cls.imc.remove(FileNode(node.path))
79 79
80 80 cls.tip = cls.imc.commit(message=unicode(commit['message']),
81 81 author=unicode(commit['author']),
82 82 date=commit['date'])
83 83
84 84 @classmethod
85 85 def tearDownClass(cls):
86 86 if not getattr(cls, 'recreate_repo_per_test', False) and \
87 87 'VCS_REMOVE_TEST_DIRS' in os.environ:
88 88 shutil.rmtree(cls.repo_path)
89 89
90 90 def setUp(self):
91 91 if getattr(self, 'recreate_repo_per_test', False):
92 92 self.__class__.setUpClass()
93 93
94 94 def tearDown(self):
95 95 if getattr(self, 'recreate_repo_per_test', False) and \
96 96 'VCS_REMOVE_TEST_DIRS' in os.environ:
97 97 shutil.rmtree(self.repo_path)
98 98
99 99
100 100 # For each backend create test case class
101 101 for alias in SCM_TESTS:
102 102 attrs = {
103 103 'backend_alias': alias,
104 104 }
105 105 cls_name = ''.join(('%s base backend test' % alias).title().split())
106 bases = (BackendTestMixin, unittest.TestCase)
106 bases = (_BackendTestMixin, unittest.TestCase)
107 107 globals()[cls_name] = type(cls_name, bases, attrs)
108 108
109 109
110 110 if __name__ == '__main__':
111 111 unittest.main()
@@ -1,108 +1,108 b''
1 1 from __future__ import with_statement
2 2
3 3 import os
4 4 import tarfile
5 5 import zipfile
6 6 import datetime
7 7 import tempfile
8 8 import StringIO
9 from kallithea.tests.vcs.base import BackendTestMixin
9 from kallithea.tests.vcs.base import _BackendTestMixin
10 10 from kallithea.tests.vcs.conf import SCM_TESTS
11 11 from kallithea.lib.vcs.exceptions import VCSError
12 12 from kallithea.lib.vcs.nodes import FileNode
13 13 from kallithea.lib.vcs.utils.compat import unittest
14 14
15 15
16 class ArchivesTestCaseMixin(BackendTestMixin):
16 class ArchivesTestCaseMixin(_BackendTestMixin):
17 17
18 18 @classmethod
19 19 def _get_commits(cls):
20 20 start_date = datetime.datetime(2010, 1, 1, 20)
21 21 for x in xrange(5):
22 22 yield {
23 23 'message': 'Commit %d' % x,
24 24 'author': 'Joe Doe <joe.doe@example.com>',
25 25 'date': start_date + datetime.timedelta(hours=12 * x),
26 26 'added': [
27 27 FileNode('%d/file_%d.txt' % (x, x),
28 28 content='Foobar %d' % x),
29 29 ],
30 30 }
31 31
32 32 def test_archive_zip(self):
33 33 path = tempfile.mkstemp()[1]
34 34 with open(path, 'wb') as f:
35 35 self.tip.fill_archive(stream=f, kind='zip', prefix='repo')
36 36 out = zipfile.ZipFile(path)
37 37
38 38 for x in xrange(5):
39 39 node_path = '%d/file_%d.txt' % (x, x)
40 40 decompressed = StringIO.StringIO()
41 41 decompressed.write(out.read('repo/' + node_path))
42 42 self.assertEqual(
43 43 decompressed.getvalue(),
44 44 self.tip.get_node(node_path).content)
45 45
46 46 def test_archive_tgz(self):
47 47 path = tempfile.mkstemp()[1]
48 48 with open(path, 'wb') as f:
49 49 self.tip.fill_archive(stream=f, kind='tgz', prefix='repo')
50 50 outdir = tempfile.mkdtemp()
51 51
52 52 outfile = tarfile.open(path, 'r|gz')
53 53 outfile.extractall(outdir)
54 54
55 55 for x in xrange(5):
56 56 node_path = '%d/file_%d.txt' % (x, x)
57 57 self.assertEqual(
58 58 open(os.path.join(outdir, 'repo/' + node_path)).read(),
59 59 self.tip.get_node(node_path).content)
60 60
61 61 def test_archive_tbz2(self):
62 62 path = tempfile.mkstemp()[1]
63 63 with open(path, 'w+b') as f:
64 64 self.tip.fill_archive(stream=f, kind='tbz2', prefix='repo')
65 65 outdir = tempfile.mkdtemp()
66 66
67 67 outfile = tarfile.open(path, 'r|bz2')
68 68 outfile.extractall(outdir)
69 69
70 70 for x in xrange(5):
71 71 node_path = '%d/file_%d.txt' % (x, x)
72 72 self.assertEqual(
73 73 open(os.path.join(outdir, 'repo/' + node_path)).read(),
74 74 self.tip.get_node(node_path).content)
75 75
76 76 def test_archive_default_stream(self):
77 77 tmppath = tempfile.mkstemp()[1]
78 78 with open(tmppath, 'w') as stream:
79 79 self.tip.fill_archive(stream=stream)
80 80 mystream = StringIO.StringIO()
81 81 self.tip.fill_archive(stream=mystream)
82 82 mystream.seek(0)
83 83 with open(tmppath, 'r') as f:
84 84 self.assertEqual(f.read(), mystream.read())
85 85
86 86 def test_archive_wrong_kind(self):
87 87 with self.assertRaises(VCSError):
88 88 self.tip.fill_archive(kind='wrong kind')
89 89
90 90 def test_archive_empty_prefix(self):
91 91 with self.assertRaises(VCSError):
92 92 self.tip.fill_archive(prefix='')
93 93
94 94 def test_archive_prefix_with_leading_slash(self):
95 95 with self.assertRaises(VCSError):
96 96 self.tip.fill_archive(prefix='/any')
97 97
98 98 # For each backend create test case class
99 99 for alias in SCM_TESTS:
100 100 attrs = {
101 101 'backend_alias': alias,
102 102 }
103 103 cls_name = ''.join(('%s archive test' % alias).title().split())
104 104 bases = (ArchivesTestCaseMixin, unittest.TestCase)
105 105 globals()[cls_name] = type(cls_name, bases, attrs)
106 106
107 107 if __name__ == '__main__':
108 108 unittest.main()
@@ -1,117 +1,117 b''
1 1 from __future__ import with_statement
2 2
3 3 import datetime
4 4 from kallithea.lib import vcs
5 5 from kallithea.lib.vcs.utils.compat import unittest
6 6 from kallithea.lib.vcs.nodes import FileNode
7 7
8 from kallithea.tests.vcs.base import BackendTestMixin
8 from kallithea.tests.vcs.base import _BackendTestMixin
9 9 from kallithea.tests.vcs.conf import SCM_TESTS
10 10
11 11
12 class BranchesTestCaseMixin(BackendTestMixin):
12 class BranchesTestCaseMixin(_BackendTestMixin):
13 13
14 14 @classmethod
15 15 def _get_commits(cls):
16 16 commits = [
17 17 {
18 18 'message': 'Initial commit',
19 19 'author': 'Joe Doe <joe.doe@example.com>',
20 20 'date': datetime.datetime(2010, 1, 1, 20),
21 21 'added': [
22 22 FileNode('foobar', content='Foobar'),
23 23 FileNode('foobar2', content='Foobar II'),
24 24 FileNode('foo/bar/baz', content='baz here!'),
25 25 ],
26 26 },
27 27 {
28 28 'message': 'Changes...',
29 29 'author': 'Jane Doe <jane.doe@example.com>',
30 30 'date': datetime.datetime(2010, 1, 1, 21),
31 31 'added': [
32 32 FileNode('some/new.txt', content='news...'),
33 33 ],
34 34 'changed': [
35 35 FileNode('foobar', 'Foobar I'),
36 36 ],
37 37 'removed': [],
38 38 },
39 39 ]
40 40 return commits
41 41
42 42 def test_simple(self):
43 43 tip = self.repo.get_changeset()
44 44 self.assertEqual(tip.date, datetime.datetime(2010, 1, 1, 21))
45 45
46 46 def test_new_branch(self):
47 47 # This check must not be removed to ensure the 'branches' LazyProperty
48 48 # gets hit *before* the new 'foobar' branch got created:
49 49 self.assertFalse('foobar' in self.repo.branches)
50 50 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
51 51 content='Documentation\n'))
52 52 foobar_tip = self.imc.commit(
53 53 message=u'New branch: foobar',
54 54 author=u'joe',
55 55 branch='foobar',
56 56 )
57 57 self.assertTrue('foobar' in self.repo.branches)
58 58 self.assertEqual(foobar_tip.branch, 'foobar')
59 59
60 60 def test_new_head(self):
61 61 tip = self.repo.get_changeset()
62 62 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
63 63 content='Documentation\n'))
64 64 foobar_tip = self.imc.commit(
65 65 message=u'New branch: foobar',
66 66 author=u'joe',
67 67 branch='foobar',
68 68 parents=[tip],
69 69 )
70 70 self.imc.change(vcs.nodes.FileNode('docs/index.txt',
71 71 content='Documentation\nand more...\n'))
72 72 newtip = self.imc.commit(
73 73 message=u'At default branch',
74 74 author=u'joe',
75 75 branch=foobar_tip.branch,
76 76 parents=[foobar_tip],
77 77 )
78 78
79 79 newest_tip = self.imc.commit(
80 80 message=u'Merged with %s' % foobar_tip.raw_id,
81 81 author=u'joe',
82 82 branch=self.backend_class.DEFAULT_BRANCH_NAME,
83 83 parents=[newtip, foobar_tip],
84 84 )
85 85
86 86 self.assertEqual(newest_tip.branch,
87 87 self.backend_class.DEFAULT_BRANCH_NAME)
88 88
89 89 def test_branch_with_slash_in_name(self):
90 90 self.imc.add(vcs.nodes.FileNode('extrafile', content='Some data\n'))
91 91 self.imc.commit(u'Branch with a slash!', author=u'joe',
92 92 branch='issue/123')
93 93 self.assertTrue('issue/123' in self.repo.branches)
94 94
95 95 def test_branch_with_slash_in_name_and_similar_without(self):
96 96 self.imc.add(vcs.nodes.FileNode('extrafile', content='Some data\n'))
97 97 self.imc.commit(u'Branch with a slash!', author=u'joe',
98 98 branch='issue/123')
99 99 self.imc.add(vcs.nodes.FileNode('extrafile II', content='Some data\n'))
100 100 self.imc.commit(u'Branch without a slash...', author=u'joe',
101 101 branch='123')
102 102 self.assertIn('issue/123', self.repo.branches)
103 103 self.assertIn('123', self.repo.branches)
104 104
105 105
106 106 # For each backend create test case class
107 107 for alias in SCM_TESTS:
108 108 attrs = {
109 109 'backend_alias': alias,
110 110 }
111 111 cls_name = ''.join(('%s branches test' % alias).title().split())
112 112 bases = (BranchesTestCaseMixin, unittest.TestCase)
113 113 globals()[cls_name] = type(cls_name, bases, attrs)
114 114
115 115
116 116 if __name__ == '__main__':
117 117 unittest.main()
@@ -1,391 +1,391 b''
1 1 # encoding: utf8
2 2 from __future__ import with_statement
3 3
4 4 import time
5 5 import datetime
6 6 from kallithea.lib import vcs
7 from kallithea.tests.vcs.base import BackendTestMixin
7 from kallithea.tests.vcs.base import _BackendTestMixin
8 8 from kallithea.tests.vcs.conf import SCM_TESTS
9 9
10 10 from kallithea.lib.vcs.backends.base import BaseChangeset
11 11 from kallithea.lib.vcs.nodes import (
12 12 FileNode, AddedFileNodesGenerator,
13 13 ChangedFileNodesGenerator, RemovedFileNodesGenerator
14 14 )
15 15 from kallithea.lib.vcs.exceptions import (
16 16 BranchDoesNotExistError, ChangesetDoesNotExistError,
17 17 RepositoryError, EmptyRepositoryError
18 18 )
19 19 from kallithea.lib.vcs.utils.compat import unittest
20 20 from kallithea.tests.vcs.conf import get_new_dir
21 21
22 22
23 23 class TestBaseChangeset(unittest.TestCase):
24 24
25 25 def test_as_dict(self):
26 26 changeset = BaseChangeset()
27 27 changeset.id = 'ID'
28 28 changeset.raw_id = 'RAW_ID'
29 29 changeset.short_id = 'SHORT_ID'
30 30 changeset.revision = 1009
31 31 changeset.date = datetime.datetime(2011, 1, 30, 1, 45)
32 32 changeset.message = 'Message of a commit'
33 33 changeset.author = 'Joe Doe <joe.doe@example.com>'
34 34 changeset.added = [FileNode('foo/bar/baz'), FileNode('foobar')]
35 35 changeset.changed = []
36 36 changeset.removed = []
37 37 self.assertEqual(changeset.as_dict(), {
38 38 'id': 'ID',
39 39 'raw_id': 'RAW_ID',
40 40 'short_id': 'SHORT_ID',
41 41 'revision': 1009,
42 42 'date': datetime.datetime(2011, 1, 30, 1, 45),
43 43 'message': 'Message of a commit',
44 44 'author': {
45 45 'name': 'Joe Doe',
46 46 'email': 'joe.doe@example.com',
47 47 },
48 48 'added': ['foo/bar/baz', 'foobar'],
49 49 'changed': [],
50 50 'removed': [],
51 51 })
52 52
53 class ChangesetsWithCommitsTestCaseixin(BackendTestMixin):
53 class _ChangesetsWithCommitsTestCaseixin(_BackendTestMixin):
54 54 recreate_repo_per_test = True
55 55
56 56 @classmethod
57 57 def _get_commits(cls):
58 58 start_date = datetime.datetime(2010, 1, 1, 20)
59 59 for x in xrange(5):
60 60 yield {
61 61 'message': 'Commit %d' % x,
62 62 'author': 'Joe Doe <joe.doe@example.com>',
63 63 'date': start_date + datetime.timedelta(hours=12 * x),
64 64 'added': [
65 65 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
66 66 ],
67 67 }
68 68
69 69 def test_new_branch(self):
70 70 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
71 71 content='Documentation\n'))
72 72 foobar_tip = self.imc.commit(
73 73 message=u'New branch: foobar',
74 74 author=u'joe',
75 75 branch='foobar',
76 76 )
77 77 self.assertTrue('foobar' in self.repo.branches)
78 78 self.assertEqual(foobar_tip.branch, 'foobar')
79 79 # 'foobar' should be the only branch that contains the new commit
80 80 self.assertNotEqual(*self.repo.branches.values())
81 81
82 82 def test_new_head_in_default_branch(self):
83 83 tip = self.repo.get_changeset()
84 84 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
85 85 content='Documentation\n'))
86 86 foobar_tip = self.imc.commit(
87 87 message=u'New branch: foobar',
88 88 author=u'joe',
89 89 branch='foobar',
90 90 parents=[tip],
91 91 )
92 92 self.imc.change(vcs.nodes.FileNode('docs/index.txt',
93 93 content='Documentation\nand more...\n'))
94 94 newtip = self.imc.commit(
95 95 message=u'At default branch',
96 96 author=u'joe',
97 97 branch=foobar_tip.branch,
98 98 parents=[foobar_tip],
99 99 )
100 100
101 101 newest_tip = self.imc.commit(
102 102 message=u'Merged with %s' % foobar_tip.raw_id,
103 103 author=u'joe',
104 104 branch=self.backend_class.DEFAULT_BRANCH_NAME,
105 105 parents=[newtip, foobar_tip],
106 106 )
107 107
108 108 self.assertEqual(newest_tip.branch,
109 109 self.backend_class.DEFAULT_BRANCH_NAME)
110 110
111 111 def test_get_changesets_respects_branch_name(self):
112 112 tip = self.repo.get_changeset()
113 113 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
114 114 content='Documentation\n'))
115 115 doc_changeset = self.imc.commit(
116 116 message=u'New branch: docs',
117 117 author=u'joe',
118 118 branch='docs',
119 119 )
120 120 self.imc.add(vcs.nodes.FileNode('newfile', content=''))
121 121 self.imc.commit(
122 122 message=u'Back in default branch',
123 123 author=u'joe',
124 124 parents=[tip],
125 125 )
126 126 default_branch_changesets = self.repo.get_changesets(
127 127 branch_name=self.repo.DEFAULT_BRANCH_NAME)
128 128 self.assertNotIn(doc_changeset, default_branch_changesets)
129 129
130 130 def test_get_changeset_by_branch(self):
131 131 for branch, sha in self.repo.branches.iteritems():
132 132 self.assertEqual(sha, self.repo.get_changeset(branch).raw_id)
133 133
134 134 def test_get_changeset_by_tag(self):
135 135 for tag, sha in self.repo.tags.iteritems():
136 136 self.assertEqual(sha, self.repo.get_changeset(tag).raw_id)
137 137
138 138 def test_get_changeset_parents(self):
139 139 for test_rev in [1, 2, 3]:
140 140 sha = self.repo.get_changeset(test_rev-1)
141 141 self.assertEqual([sha], self.repo.get_changeset(test_rev).parents)
142 142
143 143 def test_get_changeset_children(self):
144 144 for test_rev in [1, 2, 3]:
145 145 sha = self.repo.get_changeset(test_rev+1)
146 146 self.assertEqual([sha], self.repo.get_changeset(test_rev).children)
147 147
148 148
149 class ChangesetsTestCaseMixin(BackendTestMixin):
149 class _ChangesetsTestCaseMixin(_BackendTestMixin):
150 150 recreate_repo_per_test = False
151 151
152 152 @classmethod
153 153 def _get_commits(cls):
154 154 start_date = datetime.datetime(2010, 1, 1, 20)
155 155 for x in xrange(5):
156 156 yield {
157 157 'message': u'Commit %d' % x,
158 158 'author': u'Joe Doe <joe.doe@example.com>',
159 159 'date': start_date + datetime.timedelta(hours=12 * x),
160 160 'added': [
161 161 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
162 162 ],
163 163 }
164 164
165 165 def test_simple(self):
166 166 tip = self.repo.get_changeset()
167 167 self.assertEqual(tip.date, datetime.datetime(2010, 1, 3, 20))
168 168
169 169 def test_get_changesets_is_ordered_by_date(self):
170 170 changesets = list(self.repo.get_changesets())
171 171 ordered_by_date = sorted(changesets,
172 172 key=lambda cs: cs.date)
173 173 self.assertItemsEqual(changesets, ordered_by_date)
174 174
175 175 def test_get_changesets_respects_start(self):
176 176 second_id = self.repo.revisions[1]
177 177 changesets = list(self.repo.get_changesets(start=second_id))
178 178 self.assertEqual(len(changesets), 4)
179 179
180 180 def test_get_changesets_numerical_id_respects_start(self):
181 181 second_id = 1
182 182 changesets = list(self.repo.get_changesets(start=second_id))
183 183 self.assertEqual(len(changesets), 4)
184 184
185 185 def test_get_changesets_includes_start_changeset(self):
186 186 second_id = self.repo.revisions[1]
187 187 changesets = list(self.repo.get_changesets(start=second_id))
188 188 self.assertEqual(changesets[0].raw_id, second_id)
189 189
190 190 def test_get_changesets_respects_end(self):
191 191 second_id = self.repo.revisions[1]
192 192 changesets = list(self.repo.get_changesets(end=second_id))
193 193 self.assertEqual(changesets[-1].raw_id, second_id)
194 194 self.assertEqual(len(changesets), 2)
195 195
196 196 def test_get_changesets_numerical_id_respects_end(self):
197 197 second_id = 1
198 198 changesets = list(self.repo.get_changesets(end=second_id))
199 199 self.assertEqual(changesets.index(changesets[-1]), second_id)
200 200 self.assertEqual(len(changesets), 2)
201 201
202 202 def test_get_changesets_respects_both_start_and_end(self):
203 203 second_id = self.repo.revisions[1]
204 204 third_id = self.repo.revisions[2]
205 205 changesets = list(self.repo.get_changesets(start=second_id,
206 206 end=third_id))
207 207 self.assertEqual(len(changesets), 2)
208 208
209 209 def test_get_changesets_numerical_id_respects_both_start_and_end(self):
210 210 changesets = list(self.repo.get_changesets(start=2, end=3))
211 211 self.assertEqual(len(changesets), 2)
212 212
213 213 def test_get_changesets_on_empty_repo_raises_EmptyRepository_error(self):
214 214 Backend = self.get_backend()
215 215 repo_path = get_new_dir(str(time.time()))
216 216 repo = Backend(repo_path, create=True)
217 217
218 218 with self.assertRaises(EmptyRepositoryError):
219 219 list(repo.get_changesets(start='foobar'))
220 220
221 221 def test_get_changesets_includes_end_changeset(self):
222 222 second_id = self.repo.revisions[1]
223 223 changesets = list(self.repo.get_changesets(end=second_id))
224 224 self.assertEqual(changesets[-1].raw_id, second_id)
225 225
226 226 def test_get_changesets_respects_start_date(self):
227 227 start_date = datetime.datetime(2010, 2, 1)
228 228 for cs in self.repo.get_changesets(start_date=start_date):
229 229 self.assertGreaterEqual(cs.date, start_date)
230 230
231 231 def test_get_changesets_respects_end_date(self):
232 232 start_date = datetime.datetime(2010, 1, 1)
233 233 end_date = datetime.datetime(2010, 2, 1)
234 234 for cs in self.repo.get_changesets(start_date=start_date,
235 235 end_date=end_date):
236 236 self.assertGreaterEqual(cs.date, start_date)
237 237 self.assertLessEqual(cs.date, end_date)
238 238
239 239 def test_get_changesets_respects_start_date_and_end_date(self):
240 240 end_date = datetime.datetime(2010, 2, 1)
241 241 for cs in self.repo.get_changesets(end_date=end_date):
242 242 self.assertLessEqual(cs.date, end_date)
243 243
244 244 def test_get_changesets_respects_reverse(self):
245 245 changesets_id_list = [cs.raw_id for cs in
246 246 self.repo.get_changesets(reverse=True)]
247 247 self.assertItemsEqual(changesets_id_list, reversed(self.repo.revisions))
248 248
249 249 def test_get_filenodes_generator(self):
250 250 tip = self.repo.get_changeset()
251 251 filepaths = [node.path for node in tip.get_filenodes_generator()]
252 252 self.assertItemsEqual(filepaths, ['file_%d.txt' % x for x in xrange(5)])
253 253
254 254 def test_size(self):
255 255 tip = self.repo.get_changeset()
256 256 size = 5 * len('Foobar N') # Size of 5 files
257 257 self.assertEqual(tip.size, size)
258 258
259 259 def test_author(self):
260 260 tip = self.repo.get_changeset()
261 261 self.assertEqual(tip.author, u'Joe Doe <joe.doe@example.com>')
262 262
263 263 def test_author_name(self):
264 264 tip = self.repo.get_changeset()
265 265 self.assertEqual(tip.author_name, u'Joe Doe')
266 266
267 267 def test_author_email(self):
268 268 tip = self.repo.get_changeset()
269 269 self.assertEqual(tip.author_email, u'joe.doe@example.com')
270 270
271 271 def test_get_changesets_raise_changesetdoesnotexist_for_wrong_start(self):
272 272 with self.assertRaises(ChangesetDoesNotExistError):
273 273 list(self.repo.get_changesets(start='foobar'))
274 274
275 275 def test_get_changesets_raise_changesetdoesnotexist_for_wrong_end(self):
276 276 with self.assertRaises(ChangesetDoesNotExistError):
277 277 list(self.repo.get_changesets(end='foobar'))
278 278
279 279 def test_get_changesets_raise_branchdoesnotexist_for_wrong_branch_name(self):
280 280 with self.assertRaises(BranchDoesNotExistError):
281 281 list(self.repo.get_changesets(branch_name='foobar'))
282 282
283 283 def test_get_changesets_raise_repositoryerror_for_wrong_start_end(self):
284 284 start = self.repo.revisions[-1]
285 285 end = self.repo.revisions[0]
286 286 with self.assertRaises(RepositoryError):
287 287 list(self.repo.get_changesets(start=start, end=end))
288 288
289 289 def test_get_changesets_numerical_id_reversed(self):
290 290 with self.assertRaises(RepositoryError):
291 291 [x for x in self.repo.get_changesets(start=3, end=2)]
292 292
293 293 def test_get_changesets_numerical_id_respects_both_start_and_end_last(self):
294 294 with self.assertRaises(RepositoryError):
295 295 last = len(self.repo.revisions)
296 296 list(self.repo.get_changesets(start=last-1, end=last-2))
297 297
298 298 def test_get_changesets_numerical_id_last_zero_error(self):
299 299 with self.assertRaises(RepositoryError):
300 300 last = len(self.repo.revisions)
301 301 list(self.repo.get_changesets(start=last-1, end=0))
302 302
303 303
304 class ChangesetsChangesTestCaseMixin(BackendTestMixin):
304 class _ChangesetsChangesTestCaseMixin(_BackendTestMixin):
305 305 recreate_repo_per_test = False
306 306
307 307 @classmethod
308 308 def _get_commits(cls):
309 309 return [
310 310 {
311 311 'message': u'Initial',
312 312 'author': u'Joe Doe <joe.doe@example.com>',
313 313 'date': datetime.datetime(2010, 1, 1, 20),
314 314 'added': [
315 315 FileNode('foo/bar', content='foo'),
316 316 FileNode('foo/baΕ‚', content='foo'),
317 317 FileNode('foobar', content='foo'),
318 318 FileNode('qwe', content='foo'),
319 319 ],
320 320 },
321 321 {
322 322 'message': u'Massive changes',
323 323 'author': u'Joe Doe <joe.doe@example.com>',
324 324 'date': datetime.datetime(2010, 1, 1, 22),
325 325 'added': [FileNode('fallout', content='War never changes')],
326 326 'changed': [
327 327 FileNode('foo/bar', content='baz'),
328 328 FileNode('foobar', content='baz'),
329 329 ],
330 330 'removed': [FileNode('qwe')],
331 331 },
332 332 ]
333 333
334 334 def test_initial_commit(self):
335 335 changeset = self.repo.get_changeset(0)
336 336 self.assertItemsEqual(changeset.added, [
337 337 changeset.get_node('foo/bar'),
338 338 changeset.get_node('foo/baΕ‚'),
339 339 changeset.get_node('foobar'),
340 340 changeset.get_node('qwe'),
341 341 ])
342 342 self.assertItemsEqual(changeset.changed, [])
343 343 self.assertItemsEqual(changeset.removed, [])
344 344
345 345 def test_head_added(self):
346 346 changeset = self.repo.get_changeset()
347 347 self.assertTrue(isinstance(changeset.added, AddedFileNodesGenerator))
348 348 self.assertItemsEqual(changeset.added, [
349 349 changeset.get_node('fallout'),
350 350 ])
351 351 self.assertTrue(isinstance(changeset.changed, ChangedFileNodesGenerator))
352 352 self.assertItemsEqual(changeset.changed, [
353 353 changeset.get_node('foo/bar'),
354 354 changeset.get_node('foobar'),
355 355 ])
356 356 self.assertTrue(isinstance(changeset.removed, RemovedFileNodesGenerator))
357 357 self.assertEqual(len(changeset.removed), 1)
358 358 self.assertEqual(list(changeset.removed)[0].path, 'qwe')
359 359
360 360 def test_get_filemode(self):
361 361 changeset = self.repo.get_changeset()
362 362 self.assertEqual(33188, changeset.get_file_mode('foo/bar'))
363 363
364 364 def test_get_filemode_non_ascii(self):
365 365 changeset = self.repo.get_changeset()
366 366 self.assertEqual(33188, changeset.get_file_mode('foo/baΕ‚'))
367 367 self.assertEqual(33188, changeset.get_file_mode(u'foo/baΕ‚'))
368 368
369 369 # For each backend create test case class
370 370 for alias in SCM_TESTS:
371 371 attrs = {
372 372 'backend_alias': alias,
373 373 }
374 374 # tests with additional commits
375 375 cls_name = ''.join(('%s changesets with commits test' % alias).title().split())
376 bases = (ChangesetsWithCommitsTestCaseixin, unittest.TestCase)
376 bases = (_ChangesetsWithCommitsTestCaseixin, unittest.TestCase)
377 377 globals()[cls_name] = type(cls_name, bases, attrs)
378 378
379 379 # tests without additional commits
380 380 cls_name = ''.join(('%s changesets test' % alias).title().split())
381 bases = (ChangesetsTestCaseMixin, unittest.TestCase)
381 bases = (_ChangesetsTestCaseMixin, unittest.TestCase)
382 382 globals()[cls_name] = type(cls_name, bases, attrs)
383 383
384 384 # tests changes
385 385 cls_name = ''.join(('%s changesets changes test' % alias).title().split())
386 bases = (ChangesetsChangesTestCaseMixin, unittest.TestCase)
386 bases = (_ChangesetsChangesTestCaseMixin, unittest.TestCase)
387 387 globals()[cls_name] = type(cls_name, bases, attrs)
388 388
389 389
390 390 if __name__ == '__main__':
391 391 unittest.main()
@@ -1,44 +1,44 b''
1 1 from __future__ import with_statement
2 2
3 3 import datetime
4 from kallithea.tests.vcs.base import BackendTestMixin
4 from kallithea.tests.vcs.base import _BackendTestMixin
5 5 from kallithea.tests.vcs.conf import SCM_TESTS
6 6 from kallithea.lib.vcs.nodes import FileNode
7 7 from kallithea.lib.vcs.utils.compat import unittest
8 8
9 9
10 class GetitemTestCaseMixin(BackendTestMixin):
10 class GetitemTestCaseMixin(_BackendTestMixin):
11 11
12 12 @classmethod
13 13 def _get_commits(cls):
14 14 start_date = datetime.datetime(2010, 1, 1, 20)
15 15 for x in xrange(5):
16 16 yield {
17 17 'message': 'Commit %d' % x,
18 18 'author': 'Joe Doe <joe.doe@example.com>',
19 19 'date': start_date + datetime.timedelta(hours=12 * x),
20 20 'added': [
21 21 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
22 22 ],
23 23 }
24 24
25 25 def test__getitem__last_item_is_tip(self):
26 26 self.assertEqual(self.repo[-1], self.repo.get_changeset())
27 27
28 28 def test__getitem__returns_correct_items(self):
29 29 changesets = [self.repo[x] for x in xrange(len(self.repo.revisions))]
30 30 self.assertEqual(changesets, list(self.repo.get_changesets()))
31 31
32 32
33 33 # For each backend create test case class
34 34 for alias in SCM_TESTS:
35 35 attrs = {
36 36 'backend_alias': alias,
37 37 }
38 38 cls_name = ''.join(('%s getitem test' % alias).title().split())
39 39 bases = (GetitemTestCaseMixin, unittest.TestCase)
40 40 globals()[cls_name] = type(cls_name, bases, attrs)
41 41
42 42
43 43 if __name__ == '__main__':
44 44 unittest.main()
@@ -1,56 +1,56 b''
1 1 from __future__ import with_statement
2 2
3 3 import datetime
4 from kallithea.tests.vcs.base import BackendTestMixin
4 from kallithea.tests.vcs.base import _BackendTestMixin
5 5 from kallithea.tests.vcs.conf import SCM_TESTS
6 6 from kallithea.lib.vcs.nodes import FileNode
7 7 from kallithea.lib.vcs.utils.compat import unittest
8 8
9 9
10 class GetsliceTestCaseMixin(BackendTestMixin):
10 class GetsliceTestCaseMixin(_BackendTestMixin):
11 11
12 12 @classmethod
13 13 def _get_commits(cls):
14 14 start_date = datetime.datetime(2010, 1, 1, 20)
15 15 for x in xrange(5):
16 16 yield {
17 17 'message': 'Commit %d' % x,
18 18 'author': 'Joe Doe <joe.doe@example.com>',
19 19 'date': start_date + datetime.timedelta(hours=12 * x),
20 20 'added': [
21 21 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
22 22 ],
23 23 }
24 24
25 25 def test__getslice__last_item_is_tip(self):
26 26 self.assertEqual(list(self.repo[-1:])[0], self.repo.get_changeset())
27 27
28 28 def test__getslice__respects_start_index(self):
29 29 self.assertEqual(list(self.repo[2:]),
30 30 [self.repo.get_changeset(rev) for rev in self.repo.revisions[2:]])
31 31
32 32 def test__getslice__respects_negative_start_index(self):
33 33 self.assertEqual(list(self.repo[-2:]),
34 34 [self.repo.get_changeset(rev) for rev in self.repo.revisions[-2:]])
35 35
36 36 def test__getslice__respects_end_index(self):
37 37 self.assertEqual(list(self.repo[:2]),
38 38 [self.repo.get_changeset(rev) for rev in self.repo.revisions[:2]])
39 39
40 40 def test__getslice__respects_negative_end_index(self):
41 41 self.assertEqual(list(self.repo[:-2]),
42 42 [self.repo.get_changeset(rev) for rev in self.repo.revisions[:-2]])
43 43
44 44
45 45 # For each backend create test case class
46 46 for alias in SCM_TESTS:
47 47 attrs = {
48 48 'backend_alias': alias,
49 49 }
50 50 cls_name = ''.join(('%s getslice test' % alias).title().split())
51 51 bases = (GetsliceTestCaseMixin, unittest.TestCase)
52 52 globals()[cls_name] = type(cls_name, bases, attrs)
53 53
54 54
55 55 if __name__ == '__main__':
56 56 unittest.main()
@@ -1,734 +1,734 b''
1 1 from __future__ import with_statement
2 2
3 3 import os
4 4 import mock
5 5 import datetime
6 6 import urllib2
7 7 from kallithea.lib.vcs.backends.git import GitRepository, GitChangeset
8 8 from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError
9 9 from kallithea.lib.vcs.nodes import NodeKind, FileNode, DirNode, NodeState
10 10 from kallithea.lib.vcs.utils.compat import unittest
11 from kallithea.tests.vcs.base import BackendTestMixin
11 from kallithea.tests.vcs.base import _BackendTestMixin
12 12 from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_GIT_REPO_CLONE, get_new_dir
13 13
14 14
15 15 class GitRepositoryTest(unittest.TestCase):
16 16
17 17 def __check_for_existing_repo(self):
18 18 if os.path.exists(TEST_GIT_REPO_CLONE):
19 19 self.fail('Cannot test git clone repo as location %s already '
20 20 'exists. You should manually remove it first.'
21 21 % TEST_GIT_REPO_CLONE)
22 22
23 23 def setUp(self):
24 24 self.repo = GitRepository(TEST_GIT_REPO)
25 25
26 26 def test_wrong_repo_path(self):
27 27 wrong_repo_path = '/tmp/errorrepo'
28 28 self.assertRaises(RepositoryError, GitRepository, wrong_repo_path)
29 29
30 30 def test_git_cmd_injection(self):
31 31 repo_inject_path = TEST_GIT_REPO + '; echo "Cake";'
32 32 with self.assertRaises(urllib2.URLError):
33 33 # Should fail because URL will contain the parts after ; too
34 34 urlerror_fail_repo = GitRepository(get_new_dir('injection-repo'), src_url=repo_inject_path, update_after_clone=True, create=True)
35 35
36 36 with self.assertRaises(RepositoryError):
37 37 # Should fail on direct clone call, which as of this writing does not happen outside of class
38 38 clone_fail_repo = GitRepository(get_new_dir('injection-repo'), create=True)
39 39 clone_fail_repo.clone(repo_inject_path, update_after_clone=True,)
40 40
41 41 # Verify correct quoting of evil characters that should work on posix file systems
42 42 tricky_path = get_new_dir("tricky-path-repo-$'\"`")
43 43 successfully_cloned = GitRepository(tricky_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True)
44 44 # Repo should have been created
45 45 self.assertFalse(successfully_cloned._repo.bare)
46 46
47 47 tricky_path_2 = get_new_dir("tricky-path-2-repo-$'\"`")
48 48 successfully_cloned2 = GitRepository(tricky_path_2, src_url=tricky_path, bare=True, create=True)
49 49 # Repo should have been created and thus used correct quoting for clone
50 50 self.assertTrue(successfully_cloned2._repo.bare)
51 51
52 52 # Should pass because URL has been properly quoted
53 53 successfully_cloned.pull(tricky_path_2)
54 54 successfully_cloned2.fetch(tricky_path)
55 55
56 56 def test_repo_clone(self):
57 57 self.__check_for_existing_repo()
58 58 repo = GitRepository(TEST_GIT_REPO)
59 59 repo_clone = GitRepository(TEST_GIT_REPO_CLONE,
60 60 src_url=TEST_GIT_REPO, create=True, update_after_clone=True)
61 61 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
62 62 # Checking hashes of changesets should be enough
63 63 for changeset in repo.get_changesets():
64 64 raw_id = changeset.raw_id
65 65 self.assertEqual(raw_id, repo_clone.get_changeset(raw_id).raw_id)
66 66
67 67 def test_repo_clone_without_create(self):
68 68 self.assertRaises(RepositoryError, GitRepository,
69 69 TEST_GIT_REPO_CLONE + '_wo_create', src_url=TEST_GIT_REPO)
70 70
71 71 def test_repo_clone_with_update(self):
72 72 repo = GitRepository(TEST_GIT_REPO)
73 73 clone_path = TEST_GIT_REPO_CLONE + '_with_update'
74 74 repo_clone = GitRepository(clone_path,
75 75 create=True, src_url=TEST_GIT_REPO, update_after_clone=True)
76 76 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
77 77
78 78 #check if current workdir was updated
79 79 fpath = os.path.join(clone_path, 'MANIFEST.in')
80 80 self.assertEqual(True, os.path.isfile(fpath),
81 81 'Repo was cloned and updated but file %s could not be found'
82 82 % fpath)
83 83
84 84 def test_repo_clone_without_update(self):
85 85 repo = GitRepository(TEST_GIT_REPO)
86 86 clone_path = TEST_GIT_REPO_CLONE + '_without_update'
87 87 repo_clone = GitRepository(clone_path,
88 88 create=True, src_url=TEST_GIT_REPO, update_after_clone=False)
89 89 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
90 90 #check if current workdir was *NOT* updated
91 91 fpath = os.path.join(clone_path, 'MANIFEST.in')
92 92 # Make sure it's not bare repo
93 93 self.assertFalse(repo_clone._repo.bare)
94 94 self.assertEqual(False, os.path.isfile(fpath),
95 95 'Repo was cloned and updated but file %s was found'
96 96 % fpath)
97 97
98 98 def test_repo_clone_into_bare_repo(self):
99 99 repo = GitRepository(TEST_GIT_REPO)
100 100 clone_path = TEST_GIT_REPO_CLONE + '_bare.git'
101 101 repo_clone = GitRepository(clone_path, create=True,
102 102 src_url=repo.path, bare=True)
103 103 self.assertTrue(repo_clone._repo.bare)
104 104
105 105 def test_create_repo_is_not_bare_by_default(self):
106 106 repo = GitRepository(get_new_dir('not-bare-by-default'), create=True)
107 107 self.assertFalse(repo._repo.bare)
108 108
109 109 def test_create_bare_repo(self):
110 110 repo = GitRepository(get_new_dir('bare-repo'), create=True, bare=True)
111 111 self.assertTrue(repo._repo.bare)
112 112
113 113 def test_revisions(self):
114 114 # there are 112 revisions (by now)
115 115 # so we can assume they would be available from now on
116 116 subset = set([
117 117 'c1214f7e79e02fc37156ff215cd71275450cffc3',
118 118 '38b5fe81f109cb111f549bfe9bb6b267e10bc557',
119 119 'fa6600f6848800641328adbf7811fd2372c02ab2',
120 120 '102607b09cdd60e2793929c4f90478be29f85a17',
121 121 '49d3fd156b6f7db46313fac355dca1a0b94a0017',
122 122 '2d1028c054665b962fa3d307adfc923ddd528038',
123 123 'd7e0d30fbcae12c90680eb095a4f5f02505ce501',
124 124 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
125 125 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f',
126 126 '8430a588b43b5d6da365400117c89400326e7992',
127 127 'd955cd312c17b02143c04fa1099a352b04368118',
128 128 'f67b87e5c629c2ee0ba58f85197e423ff28d735b',
129 129 'add63e382e4aabc9e1afdc4bdc24506c269b7618',
130 130 'f298fe1189f1b69779a4423f40b48edf92a703fc',
131 131 'bd9b619eb41994cac43d67cf4ccc8399c1125808',
132 132 '6e125e7c890379446e98980d8ed60fba87d0f6d1',
133 133 'd4a54db9f745dfeba6933bf5b1e79e15d0af20bd',
134 134 '0b05e4ed56c802098dfc813cbe779b2f49e92500',
135 135 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
136 136 '45223f8f114c64bf4d6f853e3c35a369a6305520',
137 137 'ca1eb7957a54bce53b12d1a51b13452f95bc7c7e',
138 138 'f5ea29fc42ef67a2a5a7aecff10e1566699acd68',
139 139 '27d48942240f5b91dfda77accd2caac94708cc7d',
140 140 '622f0eb0bafd619d2560c26f80f09e3b0b0d78af',
141 141 'e686b958768ee96af8029fe19c6050b1a8dd3b2b'])
142 142 self.assertTrue(subset.issubset(set(self.repo.revisions)))
143 143
144 144
145 145
146 146 def test_slicing(self):
147 147 #4 1 5 10 95
148 148 for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5),
149 149 (10, 20, 10), (5, 100, 95)]:
150 150 revs = list(self.repo[sfrom:sto])
151 151 self.assertEqual(len(revs), size)
152 152 self.assertEqual(revs[0], self.repo.get_changeset(sfrom))
153 153 self.assertEqual(revs[-1], self.repo.get_changeset(sto - 1))
154 154
155 155
156 156 def test_branches(self):
157 157 # TODO: Need more tests here
158 158 # Removed (those are 'remotes' branches for cloned repo)
159 159 #self.assertTrue('master' in self.repo.branches)
160 160 #self.assertTrue('gittree' in self.repo.branches)
161 161 #self.assertTrue('web-branch' in self.repo.branches)
162 162 for name, id in self.repo.branches.items():
163 163 self.assertTrue(isinstance(
164 164 self.repo.get_changeset(id), GitChangeset))
165 165
166 166 def test_tags(self):
167 167 # TODO: Need more tests here
168 168 self.assertTrue('v0.1.1' in self.repo.tags)
169 169 self.assertTrue('v0.1.2' in self.repo.tags)
170 170 for name, id in self.repo.tags.items():
171 171 self.assertTrue(isinstance(
172 172 self.repo.get_changeset(id), GitChangeset))
173 173
174 174 def _test_single_changeset_cache(self, revision):
175 175 chset = self.repo.get_changeset(revision)
176 176 self.assertTrue(revision in self.repo.changesets)
177 177 self.assertTrue(chset is self.repo.changesets[revision])
178 178
179 179 def test_initial_changeset(self):
180 180 id = self.repo.revisions[0]
181 181 init_chset = self.repo.get_changeset(id)
182 182 self.assertEqual(init_chset.message, 'initial import\n')
183 183 self.assertEqual(init_chset.author,
184 184 'Marcin Kuzminski <marcin@python-blog.com>')
185 185 for path in ('vcs/__init__.py',
186 186 'vcs/backends/BaseRepository.py',
187 187 'vcs/backends/__init__.py'):
188 188 self.assertTrue(isinstance(init_chset.get_node(path), FileNode))
189 189 for path in ('', 'vcs', 'vcs/backends'):
190 190 self.assertTrue(isinstance(init_chset.get_node(path), DirNode))
191 191
192 192 self.assertRaises(NodeDoesNotExistError, init_chset.get_node, path='foobar')
193 193
194 194 node = init_chset.get_node('vcs/')
195 195 self.assertTrue(hasattr(node, 'kind'))
196 196 self.assertEqual(node.kind, NodeKind.DIR)
197 197
198 198 node = init_chset.get_node('vcs')
199 199 self.assertTrue(hasattr(node, 'kind'))
200 200 self.assertEqual(node.kind, NodeKind.DIR)
201 201
202 202 node = init_chset.get_node('vcs/__init__.py')
203 203 self.assertTrue(hasattr(node, 'kind'))
204 204 self.assertEqual(node.kind, NodeKind.FILE)
205 205
206 206 def test_not_existing_changeset(self):
207 207 self.assertRaises(RepositoryError, self.repo.get_changeset,
208 208 'f' * 40)
209 209
210 210 def test_changeset10(self):
211 211
212 212 chset10 = self.repo.get_changeset(self.repo.revisions[9])
213 213 README = """===
214 214 VCS
215 215 ===
216 216
217 217 Various Version Control System management abstraction layer for Python.
218 218
219 219 Introduction
220 220 ------------
221 221
222 222 TODO: To be written...
223 223
224 224 """
225 225 node = chset10.get_node('README.rst')
226 226 self.assertEqual(node.kind, NodeKind.FILE)
227 227 self.assertEqual(node.content, README)
228 228
229 229
230 230 class GitChangesetTest(unittest.TestCase):
231 231
232 232 def setUp(self):
233 233 self.repo = GitRepository(TEST_GIT_REPO)
234 234
235 235 def test_default_changeset(self):
236 236 tip = self.repo.get_changeset()
237 237 self.assertEqual(tip, self.repo.get_changeset(None))
238 238 self.assertEqual(tip, self.repo.get_changeset('tip'))
239 239
240 240 def test_root_node(self):
241 241 tip = self.repo.get_changeset()
242 242 self.assertTrue(tip.root is tip.get_node(''))
243 243
244 244 def test_lazy_fetch(self):
245 245 """
246 246 Test if changeset's nodes expands and are cached as we walk through
247 247 the revision. This test is somewhat hard to write as order of tests
248 248 is a key here. Written by running command after command in a shell.
249 249 """
250 250 hex = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
251 251 self.assertTrue(hex in self.repo.revisions)
252 252 chset = self.repo.get_changeset(hex)
253 253 self.assertTrue(len(chset.nodes) == 0)
254 254 root = chset.root
255 255 self.assertTrue(len(chset.nodes) == 1)
256 256 self.assertTrue(len(root.nodes) == 8)
257 257 # accessing root.nodes updates chset.nodes
258 258 self.assertTrue(len(chset.nodes) == 9)
259 259
260 260 docs = root.get_node('docs')
261 261 # we haven't yet accessed anything new as docs dir was already cached
262 262 self.assertTrue(len(chset.nodes) == 9)
263 263 self.assertTrue(len(docs.nodes) == 8)
264 264 # accessing docs.nodes updates chset.nodes
265 265 self.assertTrue(len(chset.nodes) == 17)
266 266
267 267 self.assertTrue(docs is chset.get_node('docs'))
268 268 self.assertTrue(docs is root.nodes[0])
269 269 self.assertTrue(docs is root.dirs[0])
270 270 self.assertTrue(docs is chset.get_node('docs'))
271 271
272 272 def test_nodes_with_changeset(self):
273 273 hex = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
274 274 chset = self.repo.get_changeset(hex)
275 275 root = chset.root
276 276 docs = root.get_node('docs')
277 277 self.assertTrue(docs is chset.get_node('docs'))
278 278 api = docs.get_node('api')
279 279 self.assertTrue(api is chset.get_node('docs/api'))
280 280 index = api.get_node('index.rst')
281 281 self.assertTrue(index is chset.get_node('docs/api/index.rst'))
282 282 self.assertTrue(index is chset.get_node('docs')\
283 283 .get_node('api')\
284 284 .get_node('index.rst'))
285 285
286 286 def test_branch_and_tags(self):
287 287 """
288 288 rev0 = self.repo.revisions[0]
289 289 chset0 = self.repo.get_changeset(rev0)
290 290 self.assertEqual(chset0.branch, 'master')
291 291 self.assertEqual(chset0.tags, [])
292 292
293 293 rev10 = self.repo.revisions[10]
294 294 chset10 = self.repo.get_changeset(rev10)
295 295 self.assertEqual(chset10.branch, 'master')
296 296 self.assertEqual(chset10.tags, [])
297 297
298 298 rev44 = self.repo.revisions[44]
299 299 chset44 = self.repo.get_changeset(rev44)
300 300 self.assertEqual(chset44.branch, 'web-branch')
301 301
302 302 tip = self.repo.get_changeset('tip')
303 303 self.assertTrue('tip' in tip.tags)
304 304 """
305 305 # Those tests would fail - branches are now going
306 306 # to be changed at main API in order to support git backend
307 307 pass
308 308
309 309 def _test_slices(self, limit, offset):
310 310 count = self.repo.count()
311 311 changesets = self.repo.get_changesets(limit=limit, offset=offset)
312 312 idx = 0
313 313 for changeset in changesets:
314 314 rev = offset + idx
315 315 idx += 1
316 316 rev_id = self.repo.revisions[rev]
317 317 if idx > limit:
318 318 self.fail("Exceeded limit already (getting revision %s, "
319 319 "there are %s total revisions, offset=%s, limit=%s)"
320 320 % (rev_id, count, offset, limit))
321 321 self.assertEqual(changeset, self.repo.get_changeset(rev_id))
322 322 result = list(self.repo.get_changesets(limit=limit, offset=offset))
323 323 start = offset
324 324 end = limit and offset + limit or None
325 325 sliced = list(self.repo[start:end])
326 326 self.failUnlessEqual(result, sliced,
327 327 msg="Comparison failed for limit=%s, offset=%s"
328 328 "(get_changeset returned: %s and sliced: %s"
329 329 % (limit, offset, result, sliced))
330 330
331 331 def _test_file_size(self, revision, path, size):
332 332 node = self.repo.get_changeset(revision).get_node(path)
333 333 self.assertTrue(node.is_file())
334 334 self.assertEqual(node.size, size)
335 335
336 336 def test_file_size(self):
337 337 to_check = (
338 338 ('c1214f7e79e02fc37156ff215cd71275450cffc3',
339 339 'vcs/backends/BaseRepository.py', 502),
340 340 ('d7e0d30fbcae12c90680eb095a4f5f02505ce501',
341 341 'vcs/backends/hg.py', 854),
342 342 ('6e125e7c890379446e98980d8ed60fba87d0f6d1',
343 343 'setup.py', 1068),
344 344
345 345 ('d955cd312c17b02143c04fa1099a352b04368118',
346 346 'vcs/backends/base.py', 2921),
347 347 ('ca1eb7957a54bce53b12d1a51b13452f95bc7c7e',
348 348 'vcs/backends/base.py', 3936),
349 349 ('f50f42baeed5af6518ef4b0cb2f1423f3851a941',
350 350 'vcs/backends/base.py', 6189),
351 351 )
352 352 for revision, path, size in to_check:
353 353 self._test_file_size(revision, path, size)
354 354
355 355 def test_file_history(self):
356 356 # we can only check if those revisions are present in the history
357 357 # as we cannot update this test every time file is changed
358 358 files = {
359 359 'setup.py': [
360 360 '54386793436c938cff89326944d4c2702340037d',
361 361 '51d254f0ecf5df2ce50c0b115741f4cf13985dab',
362 362 '998ed409c795fec2012b1c0ca054d99888b22090',
363 363 '5e0eb4c47f56564395f76333f319d26c79e2fb09',
364 364 '0115510b70c7229dbc5dc49036b32e7d91d23acd',
365 365 '7cb3fd1b6d8c20ba89e2264f1c8baebc8a52d36e',
366 366 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
367 367 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
368 368 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
369 369 ],
370 370 'vcs/nodes.py': [
371 371 '33fa3223355104431402a888fa77a4e9956feb3e',
372 372 'fa014c12c26d10ba682fadb78f2a11c24c8118e1',
373 373 'e686b958768ee96af8029fe19c6050b1a8dd3b2b',
374 374 'ab5721ca0a081f26bf43d9051e615af2cc99952f',
375 375 'c877b68d18e792a66b7f4c529ea02c8f80801542',
376 376 '4313566d2e417cb382948f8d9d7c765330356054',
377 377 '6c2303a793671e807d1cfc70134c9ca0767d98c2',
378 378 '54386793436c938cff89326944d4c2702340037d',
379 379 '54000345d2e78b03a99d561399e8e548de3f3203',
380 380 '1c6b3677b37ea064cb4b51714d8f7498f93f4b2b',
381 381 '2d03ca750a44440fb5ea8b751176d1f36f8e8f46',
382 382 '2a08b128c206db48c2f0b8f70df060e6db0ae4f8',
383 383 '30c26513ff1eb8e5ce0e1c6b477ee5dc50e2f34b',
384 384 'ac71e9503c2ca95542839af0ce7b64011b72ea7c',
385 385 '12669288fd13adba2a9b7dd5b870cc23ffab92d2',
386 386 '5a0c84f3e6fe3473e4c8427199d5a6fc71a9b382',
387 387 '12f2f5e2b38e6ff3fbdb5d722efed9aa72ecb0d5',
388 388 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378',
389 389 'f50f42baeed5af6518ef4b0cb2f1423f3851a941',
390 390 'd7e390a45f6aa96f04f5e7f583ad4f867431aa25',
391 391 'f15c21f97864b4f071cddfbf2750ec2e23859414',
392 392 'e906ef056cf539a4e4e5fc8003eaf7cf14dd8ade',
393 393 'ea2b108b48aa8f8c9c4a941f66c1a03315ca1c3b',
394 394 '84dec09632a4458f79f50ddbbd155506c460b4f9',
395 395 '0115510b70c7229dbc5dc49036b32e7d91d23acd',
396 396 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
397 397 '3bf1c5868e570e39569d094f922d33ced2fa3b2b',
398 398 'b8d04012574729d2c29886e53b1a43ef16dd00a1',
399 399 '6970b057cffe4aab0a792aa634c89f4bebf01441',
400 400 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f',
401 401 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
402 402 ],
403 403 'vcs/backends/git.py': [
404 404 '4cf116ad5a457530381135e2f4c453e68a1b0105',
405 405 '9a751d84d8e9408e736329767387f41b36935153',
406 406 'cb681fb539c3faaedbcdf5ca71ca413425c18f01',
407 407 '428f81bb652bcba8d631bce926e8834ff49bdcc6',
408 408 '180ab15aebf26f98f714d8c68715e0f05fa6e1c7',
409 409 '2b8e07312a2e89e92b90426ab97f349f4bce2a3a',
410 410 '50e08c506174d8645a4bb517dd122ac946a0f3bf',
411 411 '54000345d2e78b03a99d561399e8e548de3f3203',
412 412 ],
413 413 }
414 414 for path, revs in files.items():
415 415 node = self.repo.get_changeset(revs[0]).get_node(path)
416 416 node_revs = [chset.raw_id for chset in node.history]
417 417 self.assertTrue(set(revs).issubset(set(node_revs)),
418 418 "We assumed that %s is subset of revisions for which file %s "
419 419 "has been changed, and history of that node returned: %s"
420 420 % (revs, path, node_revs))
421 421
422 422 def test_file_annotate(self):
423 423 files = {
424 424 'vcs/backends/__init__.py': {
425 425 'c1214f7e79e02fc37156ff215cd71275450cffc3': {
426 426 'lines_no': 1,
427 427 'changesets': [
428 428 'c1214f7e79e02fc37156ff215cd71275450cffc3',
429 429 ],
430 430 },
431 431 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647': {
432 432 'lines_no': 21,
433 433 'changesets': [
434 434 '49d3fd156b6f7db46313fac355dca1a0b94a0017',
435 435 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
436 436 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
437 437 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
438 438 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
439 439 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
440 440 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
441 441 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
442 442 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
443 443 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
444 444 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
445 445 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
446 446 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
447 447 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
448 448 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
449 449 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
450 450 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
451 451 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
452 452 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
453 453 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
454 454 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
455 455 ],
456 456 },
457 457 'e29b67bd158580fc90fc5e9111240b90e6e86064': {
458 458 'lines_no': 32,
459 459 'changesets': [
460 460 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
461 461 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
462 462 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378',
463 463 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
464 464 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
465 465 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
466 466 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
467 467 '54000345d2e78b03a99d561399e8e548de3f3203',
468 468 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
469 469 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
470 470 '78c3f0c23b7ee935ec276acb8b8212444c33c396',
471 471 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
472 472 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
473 473 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
474 474 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
475 475 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
476 476 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
477 477 '78c3f0c23b7ee935ec276acb8b8212444c33c396',
478 478 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
479 479 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
480 480 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
481 481 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
482 482 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
483 483 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
484 484 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
485 485 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
486 486 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
487 487 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
488 488 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
489 489 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
490 490 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
491 491 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
492 492 ],
493 493 },
494 494 },
495 495 }
496 496
497 497 for fname, revision_dict in files.items():
498 498 for rev, data in revision_dict.items():
499 499 cs = self.repo.get_changeset(rev)
500 500
501 501 l1_1 = [x[1] for x in cs.get_file_annotate(fname)]
502 502 l1_2 = [x[2]().raw_id for x in cs.get_file_annotate(fname)]
503 503 self.assertEqual(l1_1, l1_2)
504 504 l1 = l1_1
505 505 l2 = files[fname][rev]['changesets']
506 506 self.assertTrue(l1 == l2 , "The lists of revision for %s@rev %s"
507 507 "from annotation list should match each other, "
508 508 "got \n%s \nvs \n%s " % (fname, rev, l1, l2))
509 509
510 510 def test_files_state(self):
511 511 """
512 512 Tests state of FileNodes.
513 513 """
514 514 node = self.repo\
515 515 .get_changeset('e6ea6d16e2f26250124a1f4b4fe37a912f9d86a0')\
516 516 .get_node('vcs/utils/diffs.py')
517 517 self.assertTrue(node.state, NodeState.ADDED)
518 518 self.assertTrue(node.added)
519 519 self.assertFalse(node.changed)
520 520 self.assertFalse(node.not_changed)
521 521 self.assertFalse(node.removed)
522 522
523 523 node = self.repo\
524 524 .get_changeset('33fa3223355104431402a888fa77a4e9956feb3e')\
525 525 .get_node('.hgignore')
526 526 self.assertTrue(node.state, NodeState.CHANGED)
527 527 self.assertFalse(node.added)
528 528 self.assertTrue(node.changed)
529 529 self.assertFalse(node.not_changed)
530 530 self.assertFalse(node.removed)
531 531
532 532 node = self.repo\
533 533 .get_changeset('e29b67bd158580fc90fc5e9111240b90e6e86064')\
534 534 .get_node('setup.py')
535 535 self.assertTrue(node.state, NodeState.NOT_CHANGED)
536 536 self.assertFalse(node.added)
537 537 self.assertFalse(node.changed)
538 538 self.assertTrue(node.not_changed)
539 539 self.assertFalse(node.removed)
540 540
541 541 # If node has REMOVED state then trying to fetch it would raise
542 542 # ChangesetError exception
543 543 chset = self.repo.get_changeset(
544 544 'fa6600f6848800641328adbf7811fd2372c02ab2')
545 545 path = 'vcs/backends/BaseRepository.py'
546 546 self.assertRaises(NodeDoesNotExistError, chset.get_node, path)
547 547 # but it would be one of ``removed`` (changeset's attribute)
548 548 self.assertTrue(path in [rf.path for rf in chset.removed])
549 549
550 550 chset = self.repo.get_changeset(
551 551 '54386793436c938cff89326944d4c2702340037d')
552 552 changed = ['setup.py', 'tests/test_nodes.py', 'vcs/backends/hg.py',
553 553 'vcs/nodes.py']
554 554 self.assertEqual(set(changed), set([f.path for f in chset.changed]))
555 555
556 556 def test_commit_message_is_unicode(self):
557 557 for cs in self.repo:
558 558 self.assertEqual(type(cs.message), unicode)
559 559
560 560 def test_changeset_author_is_unicode(self):
561 561 for cs in self.repo:
562 562 self.assertEqual(type(cs.author), unicode)
563 563
564 564 def test_repo_files_content_is_unicode(self):
565 565 changeset = self.repo.get_changeset()
566 566 for node in changeset.get_node('/'):
567 567 if node.is_file():
568 568 self.assertEqual(type(node.content), unicode)
569 569
570 570 def test_wrong_path(self):
571 571 # There is 'setup.py' in the root dir but not there:
572 572 path = 'foo/bar/setup.py'
573 573 tip = self.repo.get_changeset()
574 574 self.assertRaises(VCSError, tip.get_node, path)
575 575
576 576 def test_author_email(self):
577 577 self.assertEqual('marcin@python-blog.com',
578 578 self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3')\
579 579 .author_email)
580 580 self.assertEqual('lukasz.balcerzak@python-center.pl',
581 581 self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b')\
582 582 .author_email)
583 583 self.assertEqual('none@none',
584 584 self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992')\
585 585 .author_email)
586 586
587 587 def test_author_username(self):
588 588 self.assertEqual('Marcin Kuzminski',
589 589 self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3')\
590 590 .author_name)
591 591 self.assertEqual('Lukasz Balcerzak',
592 592 self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b')\
593 593 .author_name)
594 594 self.assertEqual('marcink',
595 595 self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992')\
596 596 .author_name)
597 597
598 598
599 599 class GitSpecificTest(unittest.TestCase):
600 600
601 601 def test_error_is_raised_for_added_if_diff_name_status_is_wrong(self):
602 602 repo = mock.MagicMock()
603 603 changeset = GitChangeset(repo, 'foobar')
604 604 changeset._diff_name_status = 'foobar'
605 605 with self.assertRaises(VCSError):
606 606 changeset.added
607 607
608 608 def test_error_is_raised_for_changed_if_diff_name_status_is_wrong(self):
609 609 repo = mock.MagicMock()
610 610 changeset = GitChangeset(repo, 'foobar')
611 611 changeset._diff_name_status = 'foobar'
612 612 with self.assertRaises(VCSError):
613 613 changeset.added
614 614
615 615 def test_error_is_raised_for_removed_if_diff_name_status_is_wrong(self):
616 616 repo = mock.MagicMock()
617 617 changeset = GitChangeset(repo, 'foobar')
618 618 changeset._diff_name_status = 'foobar'
619 619 with self.assertRaises(VCSError):
620 620 changeset.added
621 621
622 622
623 class GitSpecificWithRepoTest(BackendTestMixin, unittest.TestCase):
623 class GitSpecificWithRepoTest(_BackendTestMixin, unittest.TestCase):
624 624 backend_alias = 'git'
625 625
626 626 @classmethod
627 627 def _get_commits(cls):
628 628 return [
629 629 {
630 630 'message': 'Initial',
631 631 'author': 'Joe Doe <joe.doe@example.com>',
632 632 'date': datetime.datetime(2010, 1, 1, 20),
633 633 'added': [
634 634 FileNode('foobar/static/js/admin/base.js', content='base'),
635 635 FileNode('foobar/static/admin', content='admin',
636 636 mode=0120000), # this is a link
637 637 FileNode('foo', content='foo'),
638 638 ],
639 639 },
640 640 {
641 641 'message': 'Second',
642 642 'author': 'Joe Doe <joe.doe@example.com>',
643 643 'date': datetime.datetime(2010, 1, 1, 22),
644 644 'added': [
645 645 FileNode('foo2', content='foo2'),
646 646 ],
647 647 },
648 648 ]
649 649
650 650 def test_paths_slow_traversing(self):
651 651 cs = self.repo.get_changeset()
652 652 self.assertEqual(cs.get_node('foobar').get_node('static').get_node('js')
653 653 .get_node('admin').get_node('base.js').content, 'base')
654 654
655 655 def test_paths_fast_traversing(self):
656 656 cs = self.repo.get_changeset()
657 657 self.assertEqual(cs.get_node('foobar/static/js/admin/base.js').content,
658 658 'base')
659 659
660 660 def test_workdir_get_branch(self):
661 661 self.repo.run_git_command('checkout -b production')
662 662 # Regression test: one of following would fail if we don't check
663 663 # .git/HEAD file
664 664 self.repo.run_git_command('checkout production')
665 665 self.assertEqual(self.repo.workdir.get_branch(), 'production')
666 666 self.repo.run_git_command('checkout master')
667 667 self.assertEqual(self.repo.workdir.get_branch(), 'master')
668 668
669 669 def test_get_diff_runs_git_command_with_hashes(self):
670 670 self.repo.run_git_command = mock.Mock(return_value=['', ''])
671 671 self.repo.get_diff(0, 1)
672 672 self.repo.run_git_command.assert_called_once_with(
673 673 'diff -U%s --full-index --binary -p -M --abbrev=40 %s %s' %
674 674 (3, self.repo._get_revision(0), self.repo._get_revision(1)))
675 675
676 676 def test_get_diff_runs_git_command_with_str_hashes(self):
677 677 self.repo.run_git_command = mock.Mock(return_value=['', ''])
678 678 self.repo.get_diff(self.repo.EMPTY_CHANGESET, 1)
679 679 self.repo.run_git_command.assert_called_once_with(
680 680 'show -U%s --full-index --binary -p -M --abbrev=40 %s' %
681 681 (3, self.repo._get_revision(1)))
682 682
683 683 def test_get_diff_runs_git_command_with_path_if_its_given(self):
684 684 self.repo.run_git_command = mock.Mock(return_value=['', ''])
685 685 self.repo.get_diff(0, 1, 'foo')
686 686 self.repo.run_git_command.assert_called_once_with(
687 687 'diff -U%s --full-index --binary -p -M --abbrev=40 %s %s -- "foo"'
688 688 % (3, self.repo._get_revision(0), self.repo._get_revision(1)))
689 689
690 690
691 class GitRegressionTest(BackendTestMixin, unittest.TestCase):
691 class GitRegressionTest(_BackendTestMixin, unittest.TestCase):
692 692 backend_alias = 'git'
693 693
694 694 @classmethod
695 695 def _get_commits(cls):
696 696 return [
697 697 {
698 698 'message': 'Initial',
699 699 'author': 'Joe Doe <joe.doe@example.com>',
700 700 'date': datetime.datetime(2010, 1, 1, 20),
701 701 'added': [
702 702 FileNode('bot/__init__.py', content='base'),
703 703 FileNode('bot/templates/404.html', content='base'),
704 704 FileNode('bot/templates/500.html', content='base'),
705 705 ],
706 706 },
707 707 {
708 708 'message': 'Second',
709 709 'author': 'Joe Doe <joe.doe@example.com>',
710 710 'date': datetime.datetime(2010, 1, 1, 22),
711 711 'added': [
712 712 FileNode('bot/build/migrations/1.py', content='foo2'),
713 713 FileNode('bot/build/migrations/2.py', content='foo2'),
714 714 FileNode('bot/build/static/templates/f.html', content='foo2'),
715 715 FileNode('bot/build/static/templates/f1.html', content='foo2'),
716 716 FileNode('bot/build/templates/err.html', content='foo2'),
717 717 FileNode('bot/build/templates/err2.html', content='foo2'),
718 718 ],
719 719 },
720 720 ]
721 721
722 722 def test_similar_paths(self):
723 723 cs = self.repo.get_changeset()
724 724 paths = lambda *n:[x.path for x in n]
725 725 self.assertEqual(paths(*cs.get_nodes('bot')), ['bot/build', 'bot/templates', 'bot/__init__.py'])
726 726 self.assertEqual(paths(*cs.get_nodes('bot/build')), ['bot/build/migrations', 'bot/build/static', 'bot/build/templates'])
727 727 self.assertEqual(paths(*cs.get_nodes('bot/build/static')), ['bot/build/static/templates'])
728 728 # this get_nodes below causes troubles !
729 729 self.assertEqual(paths(*cs.get_nodes('bot/build/static/templates')), ['bot/build/static/templates/f.html', 'bot/build/static/templates/f1.html'])
730 730 self.assertEqual(paths(*cs.get_nodes('bot/build/templates')), ['bot/build/templates/err.html', 'bot/build/templates/err2.html'])
731 731 self.assertEqual(paths(*cs.get_nodes('bot/templates/')), ['bot/templates/404.html', 'bot/templates/500.html'])
732 732
733 733 if __name__ == '__main__':
734 734 unittest.main()
@@ -1,229 +1,229 b''
1 1 from __future__ import with_statement
2 2 import datetime
3 from kallithea.tests.vcs.base import BackendTestMixin
3 from kallithea.tests.vcs.base import _BackendTestMixin
4 4 from kallithea.tests.vcs.conf import SCM_TESTS
5 5 from kallithea.tests.vcs.conf import TEST_USER_CONFIG_FILE
6 6 from kallithea.lib.vcs.nodes import FileNode
7 7 from kallithea.lib.vcs.utils.compat import unittest
8 8 from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError
9 9
10 10
11 class RepositoryBaseTest(BackendTestMixin):
11 class RepositoryBaseTest(_BackendTestMixin):
12 12 recreate_repo_per_test = False
13 13
14 14 @classmethod
15 15 def _get_commits(cls):
16 16 return super(RepositoryBaseTest, cls)._get_commits()[:1]
17 17
18 18 def test_get_config_value(self):
19 19 self.assertEqual(self.repo.get_config_value('universal', 'foo',
20 20 TEST_USER_CONFIG_FILE), 'bar')
21 21
22 22 def test_get_config_value_defaults_to_None(self):
23 23 self.assertEqual(self.repo.get_config_value('universal', 'nonexist',
24 24 TEST_USER_CONFIG_FILE), None)
25 25
26 26 def test_get_user_name(self):
27 27 self.assertEqual(self.repo.get_user_name(TEST_USER_CONFIG_FILE),
28 28 'Foo Bar')
29 29
30 30 def test_get_user_email(self):
31 31 self.assertEqual(self.repo.get_user_email(TEST_USER_CONFIG_FILE),
32 32 'foo.bar@example.com')
33 33
34 34 def test_repo_equality(self):
35 35 self.assertTrue(self.repo == self.repo)
36 36
37 37 def test_repo_equality_broken_object(self):
38 38 import copy
39 39 _repo = copy.copy(self.repo)
40 40 delattr(_repo, 'path')
41 41 self.assertTrue(self.repo != _repo)
42 42
43 43 def test_repo_equality_other_object(self):
44 44 class dummy(object):
45 45 path = self.repo.path
46 46 self.assertTrue(self.repo != dummy())
47 47
48 48
49 class RepositoryGetDiffTest(BackendTestMixin):
49 class RepositoryGetDiffTest(_BackendTestMixin):
50 50
51 51 @classmethod
52 52 def _get_commits(cls):
53 53 commits = [
54 54 {
55 55 'message': 'Initial commit',
56 56 'author': 'Joe Doe <joe.doe@example.com>',
57 57 'date': datetime.datetime(2010, 1, 1, 20),
58 58 'added': [
59 59 FileNode('foobar', content='foobar'),
60 60 FileNode('foobar2', content='foobar2'),
61 61 ],
62 62 },
63 63 {
64 64 'message': 'Changed foobar, added foobar3',
65 65 'author': 'Jane Doe <jane.doe@example.com>',
66 66 'date': datetime.datetime(2010, 1, 1, 21),
67 67 'added': [
68 68 FileNode('foobar3', content='foobar3'),
69 69 ],
70 70 'changed': [
71 71 FileNode('foobar', 'FOOBAR'),
72 72 ],
73 73 },
74 74 {
75 75 'message': 'Removed foobar, changed foobar3',
76 76 'author': 'Jane Doe <jane.doe@example.com>',
77 77 'date': datetime.datetime(2010, 1, 1, 22),
78 78 'changed': [
79 79 FileNode('foobar3', content='FOOBAR\nFOOBAR\nFOOBAR\n'),
80 80 ],
81 81 'removed': [FileNode('foobar')],
82 82 },
83 83 ]
84 84 return commits
85 85
86 86 def test_raise_for_wrong(self):
87 87 with self.assertRaises(ChangesetDoesNotExistError):
88 88 self.repo.get_diff('a' * 40, 'b' * 40)
89 89
90 90
91 91 class GitRepositoryGetDiffTest(RepositoryGetDiffTest, unittest.TestCase):
92 92 backend_alias = 'git'
93 93
94 94 def test_initial_commit_diff(self):
95 95 initial_rev = self.repo.revisions[0]
96 96 self.assertEqual(self.repo.get_diff(self.repo.EMPTY_CHANGESET, initial_rev), '''diff --git a/foobar b/foobar
97 97 new file mode 100644
98 98 index 0000000000000000000000000000000000000000..f6ea0495187600e7b2288c8ac19c5886383a4632
99 99 --- /dev/null
100 100 +++ b/foobar
101 101 @@ -0,0 +1 @@
102 102 +foobar
103 103 \ No newline at end of file
104 104 diff --git a/foobar2 b/foobar2
105 105 new file mode 100644
106 106 index 0000000000000000000000000000000000000000..e8c9d6b98e3dce993a464935e1a53f50b56a3783
107 107 --- /dev/null
108 108 +++ b/foobar2
109 109 @@ -0,0 +1 @@
110 110 +foobar2
111 111 \ No newline at end of file
112 112 ''')
113 113
114 114 def test_second_changeset_diff(self):
115 115 revs = self.repo.revisions
116 116 self.assertEqual(self.repo.get_diff(revs[0], revs[1]), '''diff --git a/foobar b/foobar
117 117 index f6ea0495187600e7b2288c8ac19c5886383a4632..389865bb681b358c9b102d79abd8d5f941e96551 100644
118 118 --- a/foobar
119 119 +++ b/foobar
120 120 @@ -1 +1 @@
121 121 -foobar
122 122 \ No newline at end of file
123 123 +FOOBAR
124 124 \ No newline at end of file
125 125 diff --git a/foobar3 b/foobar3
126 126 new file mode 100644
127 127 index 0000000000000000000000000000000000000000..c11c37d41d33fb47741cff93fa5f9d798c1535b0
128 128 --- /dev/null
129 129 +++ b/foobar3
130 130 @@ -0,0 +1 @@
131 131 +foobar3
132 132 \ No newline at end of file
133 133 ''')
134 134
135 135 def test_third_changeset_diff(self):
136 136 revs = self.repo.revisions
137 137 self.assertEqual(self.repo.get_diff(revs[1], revs[2]), '''diff --git a/foobar b/foobar
138 138 deleted file mode 100644
139 139 index 389865bb681b358c9b102d79abd8d5f941e96551..0000000000000000000000000000000000000000
140 140 --- a/foobar
141 141 +++ /dev/null
142 142 @@ -1 +0,0 @@
143 143 -FOOBAR
144 144 \ No newline at end of file
145 145 diff --git a/foobar3 b/foobar3
146 146 index c11c37d41d33fb47741cff93fa5f9d798c1535b0..f9324477362684ff692aaf5b9a81e01b9e9a671c 100644
147 147 --- a/foobar3
148 148 +++ b/foobar3
149 149 @@ -1 +1,3 @@
150 150 -foobar3
151 151 \ No newline at end of file
152 152 +FOOBAR
153 153 +FOOBAR
154 154 +FOOBAR
155 155 ''')
156 156
157 157
158 158 class HgRepositoryGetDiffTest(RepositoryGetDiffTest, unittest.TestCase):
159 159 backend_alias = 'hg'
160 160
161 161 def test_initial_commit_diff(self):
162 162 initial_rev = self.repo.revisions[0]
163 163 self.assertEqual(self.repo.get_diff(self.repo.EMPTY_CHANGESET, initial_rev), '''diff --git a/foobar b/foobar
164 164 new file mode 100644
165 165 --- /dev/null
166 166 +++ b/foobar
167 167 @@ -0,0 +1,1 @@
168 168 +foobar
169 169 \ No newline at end of file
170 170 diff --git a/foobar2 b/foobar2
171 171 new file mode 100644
172 172 --- /dev/null
173 173 +++ b/foobar2
174 174 @@ -0,0 +1,1 @@
175 175 +foobar2
176 176 \ No newline at end of file
177 177 ''')
178 178
179 179 def test_second_changeset_diff(self):
180 180 revs = self.repo.revisions
181 181 self.assertEqual(self.repo.get_diff(revs[0], revs[1]), '''diff --git a/foobar b/foobar
182 182 --- a/foobar
183 183 +++ b/foobar
184 184 @@ -1,1 +1,1 @@
185 185 -foobar
186 186 \ No newline at end of file
187 187 +FOOBAR
188 188 \ No newline at end of file
189 189 diff --git a/foobar3 b/foobar3
190 190 new file mode 100644
191 191 --- /dev/null
192 192 +++ b/foobar3
193 193 @@ -0,0 +1,1 @@
194 194 +foobar3
195 195 \ No newline at end of file
196 196 ''')
197 197
198 198 def test_third_changeset_diff(self):
199 199 revs = self.repo.revisions
200 200 self.assertEqual(self.repo.get_diff(revs[1], revs[2]), '''diff --git a/foobar b/foobar
201 201 deleted file mode 100644
202 202 --- a/foobar
203 203 +++ /dev/null
204 204 @@ -1,1 +0,0 @@
205 205 -FOOBAR
206 206 \ No newline at end of file
207 207 diff --git a/foobar3 b/foobar3
208 208 --- a/foobar3
209 209 +++ b/foobar3
210 210 @@ -1,1 +1,3 @@
211 211 -foobar3
212 212 \ No newline at end of file
213 213 +FOOBAR
214 214 +FOOBAR
215 215 +FOOBAR
216 216 ''')
217 217
218 218
219 219 # For each backend create test case class
220 220 for alias in SCM_TESTS:
221 221 attrs = {
222 222 'backend_alias': alias,
223 223 }
224 224 cls_name = alias.capitalize() + RepositoryBaseTest.__name__
225 225 bases = (RepositoryBaseTest, unittest.TestCase)
226 226 globals()[cls_name] = type(cls_name, bases, attrs)
227 227
228 228 if __name__ == '__main__':
229 229 unittest.main()
@@ -1,61 +1,61 b''
1 1 from __future__ import with_statement
2 2
3 from kallithea.tests.vcs.base import BackendTestMixin
3 from kallithea.tests.vcs.base import _BackendTestMixin
4 4 from kallithea.tests.vcs.conf import SCM_TESTS
5 5 from kallithea.lib.vcs.exceptions import TagAlreadyExistError
6 6 from kallithea.lib.vcs.exceptions import TagDoesNotExistError
7 7 from kallithea.lib.vcs.utils.compat import unittest
8 8
9 9
10 class TagsTestCaseMixin(BackendTestMixin):
10 class TagsTestCaseMixin(_BackendTestMixin):
11 11
12 12 def test_new_tag(self):
13 13 tip = self.repo.get_changeset()
14 14 tagsize = len(self.repo.tags)
15 15 tag = self.repo.tag('last-commit', 'joe', tip.raw_id)
16 16
17 17 self.assertEqual(len(self.repo.tags), tagsize + 1)
18 18 for top, dirs, files in tip.walk():
19 19 self.assertEqual(top, tag.get_node(top.path))
20 20
21 21 def test_tag_already_exist(self):
22 22 tip = self.repo.get_changeset()
23 23 self.repo.tag('last-commit', 'joe', tip.raw_id)
24 24
25 25 self.assertRaises(TagAlreadyExistError,
26 26 self.repo.tag, 'last-commit', 'joe', tip.raw_id)
27 27
28 28 chset = self.repo.get_changeset(0)
29 29 self.assertRaises(TagAlreadyExistError,
30 30 self.repo.tag, 'last-commit', 'jane', chset.raw_id)
31 31
32 32 def test_remove_tag(self):
33 33 tip = self.repo.get_changeset()
34 34 self.repo.tag('last-commit', 'joe', tip.raw_id)
35 35 tagsize = len(self.repo.tags)
36 36
37 37 self.repo.remove_tag('last-commit', user='evil joe')
38 38 self.assertEqual(len(self.repo.tags), tagsize - 1)
39 39
40 40 def test_remove_tag_which_does_not_exist(self):
41 41 self.assertRaises(TagDoesNotExistError,
42 42 self.repo.remove_tag, 'last-commit', user='evil joe')
43 43
44 44 def test_name_with_slash(self):
45 45 self.repo.tag('19/10/11', 'joe')
46 46 self.assertTrue('19/10/11' in self.repo.tags)
47 47 self.repo.tag('11', 'joe')
48 48 self.assertTrue('11' in self.repo.tags)
49 49
50 50 # For each backend create test case class
51 51 for alias in SCM_TESTS:
52 52 attrs = {
53 53 'backend_alias': alias,
54 54 }
55 55 cls_name = ''.join(('%s tags test' % alias).title().split())
56 56 bases = (TagsTestCaseMixin, unittest.TestCase)
57 57 globals()[cls_name] = type(cls_name, bases, attrs)
58 58
59 59
60 60 if __name__ == '__main__':
61 61 unittest.main()
@@ -1,98 +1,98 b''
1 1 from __future__ import with_statement
2 2
3 3 import datetime
4 4 from kallithea.lib.vcs.nodes import FileNode
5 5 from kallithea.lib.vcs.utils.compat import unittest
6 from kallithea.tests.vcs.base import BackendTestMixin
6 from kallithea.tests.vcs.base import _BackendTestMixin
7 7 from kallithea.tests.vcs.conf import SCM_TESTS
8 8
9 9
10 class WorkdirTestCaseMixin(BackendTestMixin):
10 class WorkdirTestCaseMixin(_BackendTestMixin):
11 11
12 12 @classmethod
13 13 def _get_commits(cls):
14 14 commits = [
15 15 {
16 16 'message': u'Initial commit',
17 17 'author': u'Joe Doe <joe.doe@example.com>',
18 18 'date': datetime.datetime(2010, 1, 1, 20),
19 19 'added': [
20 20 FileNode('foobar', content='Foobar'),
21 21 FileNode('foobar2', content='Foobar II'),
22 22 FileNode('foo/bar/baz', content='baz here!'),
23 23 ],
24 24 },
25 25 {
26 26 'message': u'Changes...',
27 27 'author': u'Jane Doe <jane.doe@example.com>',
28 28 'date': datetime.datetime(2010, 1, 1, 21),
29 29 'added': [
30 30 FileNode('some/new.txt', content='news...'),
31 31 ],
32 32 'changed': [
33 33 FileNode('foobar', 'Foobar I'),
34 34 ],
35 35 'removed': [],
36 36 },
37 37 ]
38 38 return commits
39 39
40 40 def test_get_branch_for_default_branch(self):
41 41 self.assertEqual(self.repo.workdir.get_branch(),
42 42 self.repo.DEFAULT_BRANCH_NAME)
43 43
44 44 def test_get_branch_after_adding_one(self):
45 45 self.imc.add(FileNode('docs/index.txt',
46 46 content='Documentation\n'))
47 47 self.imc.commit(
48 48 message=u'New branch: foobar',
49 49 author=u'joe',
50 50 branch='foobar',
51 51 )
52 52 self.assertEqual(self.repo.workdir.get_branch(), self.default_branch)
53 53
54 54 def test_get_changeset(self):
55 55 old_head = self.repo.get_changeset()
56 56 self.imc.add(FileNode('docs/index.txt',
57 57 content='Documentation\n'))
58 58 head = self.imc.commit(
59 59 message=u'New branch: foobar',
60 60 author=u'joe',
61 61 branch='foobar',
62 62 )
63 63 self.assertEqual(self.repo.workdir.get_branch(), self.default_branch)
64 64 self.repo.workdir.checkout_branch('foobar')
65 65 self.assertEqual(self.repo.workdir.get_changeset(), head)
66 66
67 67 # Make sure that old head is still there after update to defualt branch
68 68 self.repo.workdir.checkout_branch(self.default_branch)
69 69 self.assertEqual(self.repo.workdir.get_changeset(), old_head)
70 70
71 71 def test_checkout_branch(self):
72 72 from kallithea.lib.vcs.exceptions import BranchDoesNotExistError
73 73 # first, 'foobranch' does not exist.
74 74 self.assertRaises(BranchDoesNotExistError, self.repo.workdir.checkout_branch,
75 75 branch='foobranch')
76 76 # create new branch 'foobranch'.
77 77 self.imc.add(FileNode('file1', content='blah'))
78 78 self.imc.commit(message=u'asd', author=u'john', branch='foobranch')
79 79 # go back to the default branch
80 80 self.repo.workdir.checkout_branch()
81 81 self.assertEqual(self.repo.workdir.get_branch(), self.backend_class.DEFAULT_BRANCH_NAME)
82 82 # checkout 'foobranch'
83 83 self.repo.workdir.checkout_branch('foobranch')
84 84 self.assertEqual(self.repo.workdir.get_branch(), 'foobranch')
85 85
86 86
87 87 # For each backend create test case class
88 88 for alias in SCM_TESTS:
89 89 attrs = {
90 90 'backend_alias': alias,
91 91 }
92 92 cls_name = ''.join(('%s branch test' % alias).title().split())
93 93 bases = (WorkdirTestCaseMixin, unittest.TestCase)
94 94 globals()[cls_name] = type(cls_name, bases, attrs)
95 95
96 96
97 97 if __name__ == '__main__':
98 98 unittest.main()
General Comments 0
You need to be logged in to leave comments. Login now