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