Show More
@@ -1,2817 +1,2818 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 the JSON-RPC web api. |
|
16 | Tests for the JSON-RPC web api. | |
17 | """ |
|
17 | """ | |
18 |
|
18 | |||
19 | import os |
|
19 | import os | |
20 | import random |
|
20 | import random | |
21 | import re |
|
21 | import re | |
22 | import string |
|
22 | import string | |
23 | from typing import Sized |
|
23 | from typing import Sized | |
24 |
|
24 | |||
25 | import mock |
|
25 | import mock | |
26 | import pytest |
|
26 | import pytest | |
27 | from webtest import TestApp |
|
27 | from webtest import TestApp | |
28 |
|
28 | |||
29 | from kallithea.lib import ext_json |
|
29 | from kallithea.lib import ext_json | |
30 | from kallithea.lib.auth import AuthUser |
|
30 | from kallithea.lib.auth import AuthUser | |
31 | from kallithea.lib.utils2 import ascii_bytes |
|
31 | from kallithea.lib.utils2 import ascii_bytes | |
32 | from kallithea.model import db, meta |
|
32 | from kallithea.model import db, meta | |
33 | from kallithea.model.changeset_status import ChangesetStatusModel |
|
33 | from kallithea.model.changeset_status import ChangesetStatusModel | |
34 | from kallithea.model.gist import GistModel |
|
34 | from kallithea.model.gist import GistModel | |
35 | from kallithea.model.pull_request import PullRequestModel |
|
35 | from kallithea.model.pull_request import PullRequestModel | |
36 | from kallithea.model.repo import RepoModel |
|
36 | from kallithea.model.repo import RepoModel | |
37 | from kallithea.model.repo_group import RepoGroupModel |
|
37 | from kallithea.model.repo_group import RepoGroupModel | |
38 | from kallithea.model.scm import ScmModel |
|
38 | from kallithea.model.scm import ScmModel | |
39 | from kallithea.model.user import UserModel |
|
39 | from kallithea.model.user import UserModel | |
40 | from kallithea.model.user_group import UserGroupModel |
|
40 | from kallithea.model.user_group import UserGroupModel | |
41 | from kallithea.tests import base |
|
41 | from kallithea.tests import base | |
42 | from kallithea.tests.fixture import Fixture, raise_exception |
|
42 | from kallithea.tests.fixture import Fixture, raise_exception | |
43 |
|
43 | |||
44 |
|
44 | |||
45 | API_URL = '/_admin/api' |
|
45 | API_URL = '/_admin/api' | |
46 | TEST_USER_GROUP = 'test_user_group' |
|
46 | TEST_USER_GROUP = 'test_user_group' | |
47 | TEST_REPO_GROUP = 'test_repo_group' |
|
47 | TEST_REPO_GROUP = 'test_repo_group' | |
48 |
|
48 | |||
49 | fixture = Fixture() |
|
49 | fixture = Fixture() | |
50 |
|
50 | |||
51 |
|
51 | |||
52 | def _build_data(apikey, method, **kw): |
|
52 | def _build_data(apikey, method, **kw): | |
53 | """ |
|
53 | """ | |
54 | Builds API data with given random ID |
|
54 | Builds API data with given random ID | |
55 | For convenience, the json is returned as str |
|
55 | For convenience, the json is returned as str | |
56 | """ |
|
56 | """ | |
57 | random_id = random.randrange(1, 9999) |
|
57 | random_id = random.randrange(1, 9999) | |
58 | return random_id, ext_json.dumps({ |
|
58 | return random_id, ext_json.dumps({ | |
59 | "id": random_id, |
|
59 | "id": random_id, | |
60 | "api_key": apikey, |
|
60 | "api_key": apikey, | |
61 | "method": method, |
|
61 | "method": method, | |
62 | "args": kw |
|
62 | "args": kw | |
63 | }) |
|
63 | }) | |
64 |
|
64 | |||
65 |
|
65 | |||
66 | jsonify = lambda obj: ext_json.loads(ext_json.dumps(obj)) |
|
66 | def jsonify(obj): | |
|
67 | return ext_json.loads(ext_json.dumps(obj)) | |||
67 |
|
68 | |||
68 |
|
69 | |||
69 | def api_call(test_obj, params): |
|
70 | def api_call(test_obj, params): | |
70 | response = test_obj.app.post(API_URL, content_type='application/json', |
|
71 | response = test_obj.app.post(API_URL, content_type='application/json', | |
71 | params=params) |
|
72 | params=params) | |
72 | return response |
|
73 | return response | |
73 |
|
74 | |||
74 |
|
75 | |||
75 | ## helpers |
|
76 | ## helpers | |
76 | def make_user_group(name=TEST_USER_GROUP): |
|
77 | def make_user_group(name=TEST_USER_GROUP): | |
77 | gr = fixture.create_user_group(name, cur_user=base.TEST_USER_ADMIN_LOGIN) |
|
78 | gr = fixture.create_user_group(name, cur_user=base.TEST_USER_ADMIN_LOGIN) | |
78 | UserGroupModel().add_user_to_group(user_group=gr, |
|
79 | UserGroupModel().add_user_to_group(user_group=gr, | |
79 | user=base.TEST_USER_ADMIN_LOGIN) |
|
80 | user=base.TEST_USER_ADMIN_LOGIN) | |
80 | meta.Session().commit() |
|
81 | meta.Session().commit() | |
81 | return gr |
|
82 | return gr | |
82 |
|
83 | |||
83 |
|
84 | |||
84 | def make_repo_group(name=TEST_REPO_GROUP): |
|
85 | def make_repo_group(name=TEST_REPO_GROUP): | |
85 | gr = fixture.create_repo_group(name, cur_user=base.TEST_USER_ADMIN_LOGIN) |
|
86 | gr = fixture.create_repo_group(name, cur_user=base.TEST_USER_ADMIN_LOGIN) | |
86 | meta.Session().commit() |
|
87 | meta.Session().commit() | |
87 | return gr |
|
88 | return gr | |
88 |
|
89 | |||
89 |
|
90 | |||
90 | class _BaseTestApi(object): |
|
91 | class _BaseTestApi(object): | |
91 | app: TestApp # assigned by app_fixture in subclass TestController mixin |
|
92 | app: TestApp # assigned by app_fixture in subclass TestController mixin | |
92 | # assigned in subclass: |
|
93 | # assigned in subclass: | |
93 | REPO: str |
|
94 | REPO: str | |
94 | REPO_TYPE: str |
|
95 | REPO_TYPE: str | |
95 | TEST_REVISION: str |
|
96 | TEST_REVISION: str | |
96 | TEST_PR_SRC: str |
|
97 | TEST_PR_SRC: str | |
97 | TEST_PR_DST: str |
|
98 | TEST_PR_DST: str | |
98 | TEST_PR_REVISIONS: Sized |
|
99 | TEST_PR_REVISIONS: Sized | |
99 |
|
100 | |||
100 | @classmethod |
|
101 | @classmethod | |
101 | def setup_class(cls): |
|
102 | def setup_class(cls): | |
102 | cls.usr = db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) |
|
103 | cls.usr = db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) | |
103 | cls.apikey = cls.usr.api_key |
|
104 | cls.apikey = cls.usr.api_key | |
104 | cls.test_user = UserModel().create_or_update( |
|
105 | cls.test_user = UserModel().create_or_update( | |
105 | username='test-api', |
|
106 | username='test-api', | |
106 | password='test', |
|
107 | password='test', | |
107 | email='test@example.com', |
|
108 | email='test@example.com', | |
108 | firstname='first', |
|
109 | firstname='first', | |
109 | lastname='last' |
|
110 | lastname='last' | |
110 | ) |
|
111 | ) | |
111 | meta.Session().commit() |
|
112 | meta.Session().commit() | |
112 | cls.TEST_USER_LOGIN = cls.test_user.username |
|
113 | cls.TEST_USER_LOGIN = cls.test_user.username | |
113 | cls.apikey_regular = cls.test_user.api_key |
|
114 | cls.apikey_regular = cls.test_user.api_key | |
114 |
|
115 | |||
115 | @classmethod |
|
116 | @classmethod | |
116 | def teardown_class(cls): |
|
117 | def teardown_class(cls): | |
117 | pass |
|
118 | pass | |
118 |
|
119 | |||
119 | def setup_method(self, method): |
|
120 | def setup_method(self, method): | |
120 | make_user_group() |
|
121 | make_user_group() | |
121 | make_repo_group() |
|
122 | make_repo_group() | |
122 |
|
123 | |||
123 | def teardown_method(self, method): |
|
124 | def teardown_method(self, method): | |
124 | fixture.destroy_user_group(TEST_USER_GROUP) |
|
125 | fixture.destroy_user_group(TEST_USER_GROUP) | |
125 | fixture.destroy_gists() |
|
126 | fixture.destroy_gists() | |
126 | fixture.destroy_repo_group(TEST_REPO_GROUP) |
|
127 | fixture.destroy_repo_group(TEST_REPO_GROUP) | |
127 |
|
128 | |||
128 | def _compare_ok(self, id_, expected, given): |
|
129 | def _compare_ok(self, id_, expected, given): | |
129 | expected = jsonify({ |
|
130 | expected = jsonify({ | |
130 | 'id': id_, |
|
131 | 'id': id_, | |
131 | 'error': None, |
|
132 | 'error': None, | |
132 | 'result': expected |
|
133 | 'result': expected | |
133 | }) |
|
134 | }) | |
134 | given = ext_json.loads(given) |
|
135 | given = ext_json.loads(given) | |
135 | assert expected == given, (expected, given) |
|
136 | assert expected == given, (expected, given) | |
136 |
|
137 | |||
137 | def _compare_error(self, id_, expected, given): |
|
138 | def _compare_error(self, id_, expected, given): | |
138 | expected = jsonify({ |
|
139 | expected = jsonify({ | |
139 | 'id': id_, |
|
140 | 'id': id_, | |
140 | 'error': expected, |
|
141 | 'error': expected, | |
141 | 'result': None |
|
142 | 'result': None | |
142 | }) |
|
143 | }) | |
143 | given = ext_json.loads(given) |
|
144 | given = ext_json.loads(given) | |
144 | assert expected == given, (expected, given) |
|
145 | assert expected == given, (expected, given) | |
145 |
|
146 | |||
146 | def test_api_wrong_key(self): |
|
147 | def test_api_wrong_key(self): | |
147 | id_, params = _build_data('trololo', 'get_user') |
|
148 | id_, params = _build_data('trololo', 'get_user') | |
148 | response = api_call(self, params) |
|
149 | response = api_call(self, params) | |
149 |
|
150 | |||
150 | expected = 'Invalid API key' |
|
151 | expected = 'Invalid API key' | |
151 | self._compare_error(id_, expected, given=response.body) |
|
152 | self._compare_error(id_, expected, given=response.body) | |
152 |
|
153 | |||
153 | def test_api_missing_non_optional_param(self): |
|
154 | def test_api_missing_non_optional_param(self): | |
154 | id_, params = _build_data(self.apikey, 'get_repo') |
|
155 | id_, params = _build_data(self.apikey, 'get_repo') | |
155 | response = api_call(self, params) |
|
156 | response = api_call(self, params) | |
156 |
|
157 | |||
157 | expected = 'Missing non optional `repoid` arg in JSON DATA' |
|
158 | expected = 'Missing non optional `repoid` arg in JSON DATA' | |
158 | self._compare_error(id_, expected, given=response.body) |
|
159 | self._compare_error(id_, expected, given=response.body) | |
159 |
|
160 | |||
160 | def test_api_missing_non_optional_param_args_null(self): |
|
161 | def test_api_missing_non_optional_param_args_null(self): | |
161 | id_, params = _build_data(self.apikey, 'get_repo') |
|
162 | id_, params = _build_data(self.apikey, 'get_repo') | |
162 | params = params.replace('"args": {}', '"args": null') |
|
163 | params = params.replace('"args": {}', '"args": null') | |
163 | response = api_call(self, params) |
|
164 | response = api_call(self, params) | |
164 |
|
165 | |||
165 | expected = 'Missing non optional `repoid` arg in JSON DATA' |
|
166 | expected = 'Missing non optional `repoid` arg in JSON DATA' | |
166 | self._compare_error(id_, expected, given=response.body) |
|
167 | self._compare_error(id_, expected, given=response.body) | |
167 |
|
168 | |||
168 | def test_api_missing_non_optional_param_args_bad(self): |
|
169 | def test_api_missing_non_optional_param_args_bad(self): | |
169 | id_, params = _build_data(self.apikey, 'get_repo') |
|
170 | id_, params = _build_data(self.apikey, 'get_repo') | |
170 | params = params.replace('"args": {}', '"args": 1') |
|
171 | params = params.replace('"args": {}', '"args": 1') | |
171 | response = api_call(self, params) |
|
172 | response = api_call(self, params) | |
172 |
|
173 | |||
173 | expected = 'Missing non optional `repoid` arg in JSON DATA' |
|
174 | expected = 'Missing non optional `repoid` arg in JSON DATA' | |
174 | self._compare_error(id_, expected, given=response.body) |
|
175 | self._compare_error(id_, expected, given=response.body) | |
175 |
|
176 | |||
176 | def test_api_args_is_null(self): |
|
177 | def test_api_args_is_null(self): | |
177 | id_, params = _build_data(self.apikey, 'get_users', ) |
|
178 | id_, params = _build_data(self.apikey, 'get_users', ) | |
178 | params = params.replace('"args": {}', '"args": null') |
|
179 | params = params.replace('"args": {}', '"args": null') | |
179 | response = api_call(self, params) |
|
180 | response = api_call(self, params) | |
180 | assert response.status == '200 OK' |
|
181 | assert response.status == '200 OK' | |
181 |
|
182 | |||
182 | def test_api_args_is_bad(self): |
|
183 | def test_api_args_is_bad(self): | |
183 | id_, params = _build_data(self.apikey, 'get_users', ) |
|
184 | id_, params = _build_data(self.apikey, 'get_users', ) | |
184 | params = params.replace('"args": {}', '"args": 1') |
|
185 | params = params.replace('"args": {}', '"args": 1') | |
185 | response = api_call(self, params) |
|
186 | response = api_call(self, params) | |
186 | assert response.status == '200 OK' |
|
187 | assert response.status == '200 OK' | |
187 |
|
188 | |||
188 | def test_api_args_different_args(self): |
|
189 | def test_api_args_different_args(self): | |
189 | expected = { |
|
190 | expected = { | |
190 | 'ascii_letters': string.ascii_letters, |
|
191 | 'ascii_letters': string.ascii_letters, | |
191 | 'ws': string.whitespace, |
|
192 | 'ws': string.whitespace, | |
192 | 'printables': string.printable |
|
193 | 'printables': string.printable | |
193 | } |
|
194 | } | |
194 | id_, params = _build_data(self.apikey, 'test', args=expected) |
|
195 | id_, params = _build_data(self.apikey, 'test', args=expected) | |
195 | response = api_call(self, params) |
|
196 | response = api_call(self, params) | |
196 | assert response.status == '200 OK' |
|
197 | assert response.status == '200 OK' | |
197 | self._compare_ok(id_, expected, response.body) |
|
198 | self._compare_ok(id_, expected, response.body) | |
198 |
|
199 | |||
199 | def test_api_get_users(self): |
|
200 | def test_api_get_users(self): | |
200 | id_, params = _build_data(self.apikey, 'get_users', ) |
|
201 | id_, params = _build_data(self.apikey, 'get_users', ) | |
201 | response = api_call(self, params) |
|
202 | response = api_call(self, params) | |
202 | ret_all = [] |
|
203 | ret_all = [] | |
203 | _users = db.User.query().filter_by(is_default_user=False) \ |
|
204 | _users = db.User.query().filter_by(is_default_user=False) \ | |
204 | .order_by(db.User.username).all() |
|
205 | .order_by(db.User.username).all() | |
205 | for usr in _users: |
|
206 | for usr in _users: | |
206 | ret = usr.get_api_data() |
|
207 | ret = usr.get_api_data() | |
207 | ret_all.append(jsonify(ret)) |
|
208 | ret_all.append(jsonify(ret)) | |
208 | expected = ret_all |
|
209 | expected = ret_all | |
209 | self._compare_ok(id_, expected, given=response.body) |
|
210 | self._compare_ok(id_, expected, given=response.body) | |
210 |
|
211 | |||
211 | def test_api_get_user(self): |
|
212 | def test_api_get_user(self): | |
212 | id_, params = _build_data(self.apikey, 'get_user', |
|
213 | id_, params = _build_data(self.apikey, 'get_user', | |
213 | userid=base.TEST_USER_ADMIN_LOGIN) |
|
214 | userid=base.TEST_USER_ADMIN_LOGIN) | |
214 | response = api_call(self, params) |
|
215 | response = api_call(self, params) | |
215 |
|
216 | |||
216 | usr = db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) |
|
217 | usr = db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) | |
217 | ret = usr.get_api_data() |
|
218 | ret = usr.get_api_data() | |
218 | ret['permissions'] = AuthUser(dbuser=usr).permissions |
|
219 | ret['permissions'] = AuthUser(dbuser=usr).permissions | |
219 |
|
220 | |||
220 | expected = ret |
|
221 | expected = ret | |
221 | self._compare_ok(id_, expected, given=response.body) |
|
222 | self._compare_ok(id_, expected, given=response.body) | |
222 |
|
223 | |||
223 | def test_api_get_user_that_does_not_exist(self): |
|
224 | def test_api_get_user_that_does_not_exist(self): | |
224 | id_, params = _build_data(self.apikey, 'get_user', |
|
225 | id_, params = _build_data(self.apikey, 'get_user', | |
225 | userid='trololo') |
|
226 | userid='trololo') | |
226 | response = api_call(self, params) |
|
227 | response = api_call(self, params) | |
227 |
|
228 | |||
228 | expected = "user `%s` does not exist" % 'trololo' |
|
229 | expected = "user `%s` does not exist" % 'trololo' | |
229 | self._compare_error(id_, expected, given=response.body) |
|
230 | self._compare_error(id_, expected, given=response.body) | |
230 |
|
231 | |||
231 | def test_api_get_user_without_giving_userid(self): |
|
232 | def test_api_get_user_without_giving_userid(self): | |
232 | id_, params = _build_data(self.apikey, 'get_user') |
|
233 | id_, params = _build_data(self.apikey, 'get_user') | |
233 | response = api_call(self, params) |
|
234 | response = api_call(self, params) | |
234 |
|
235 | |||
235 | usr = db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) |
|
236 | usr = db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) | |
236 | ret = usr.get_api_data() |
|
237 | ret = usr.get_api_data() | |
237 | ret['permissions'] = AuthUser(dbuser=usr).permissions |
|
238 | ret['permissions'] = AuthUser(dbuser=usr).permissions | |
238 |
|
239 | |||
239 | expected = ret |
|
240 | expected = ret | |
240 | self._compare_ok(id_, expected, given=response.body) |
|
241 | self._compare_ok(id_, expected, given=response.body) | |
241 |
|
242 | |||
242 | def test_api_get_user_without_giving_userid_non_admin(self): |
|
243 | def test_api_get_user_without_giving_userid_non_admin(self): | |
243 | id_, params = _build_data(self.apikey_regular, 'get_user') |
|
244 | id_, params = _build_data(self.apikey_regular, 'get_user') | |
244 | response = api_call(self, params) |
|
245 | response = api_call(self, params) | |
245 |
|
246 | |||
246 | usr = db.User.get_by_username(self.TEST_USER_LOGIN) |
|
247 | usr = db.User.get_by_username(self.TEST_USER_LOGIN) | |
247 | ret = usr.get_api_data() |
|
248 | ret = usr.get_api_data() | |
248 | ret['permissions'] = AuthUser(dbuser=usr).permissions |
|
249 | ret['permissions'] = AuthUser(dbuser=usr).permissions | |
249 |
|
250 | |||
250 | expected = ret |
|
251 | expected = ret | |
251 | self._compare_ok(id_, expected, given=response.body) |
|
252 | self._compare_ok(id_, expected, given=response.body) | |
252 |
|
253 | |||
253 | def test_api_get_user_with_giving_userid_non_admin(self): |
|
254 | def test_api_get_user_with_giving_userid_non_admin(self): | |
254 | id_, params = _build_data(self.apikey_regular, 'get_user', |
|
255 | id_, params = _build_data(self.apikey_regular, 'get_user', | |
255 | userid=self.TEST_USER_LOGIN) |
|
256 | userid=self.TEST_USER_LOGIN) | |
256 | response = api_call(self, params) |
|
257 | response = api_call(self, params) | |
257 |
|
258 | |||
258 | expected = 'userid is not the same as your user' |
|
259 | expected = 'userid is not the same as your user' | |
259 | self._compare_error(id_, expected, given=response.body) |
|
260 | self._compare_error(id_, expected, given=response.body) | |
260 |
|
261 | |||
261 | def test_api_pull_remote(self): |
|
262 | def test_api_pull_remote(self): | |
262 | # Note: pulling from local repos is a mis-feature - it will bypass access control |
|
263 | # Note: pulling from local repos is a mis-feature - it will bypass access control | |
263 | # ... but ok, if the path already has been set in the database |
|
264 | # ... but ok, if the path already has been set in the database | |
264 | repo_name = 'test_pull' |
|
265 | repo_name = 'test_pull' | |
265 | r = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) |
|
266 | r = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) | |
266 | # hack around that clone_uri can't be set to to a local path |
|
267 | # hack around that clone_uri can't be set to to a local path | |
267 | # (as shown by test_api_create_repo_clone_uri_local) |
|
268 | # (as shown by test_api_create_repo_clone_uri_local) | |
268 | r.clone_uri = os.path.join(db.Ui.get_by_key('paths', '/').ui_value, self.REPO) |
|
269 | r.clone_uri = os.path.join(db.Ui.get_by_key('paths', '/').ui_value, self.REPO) | |
269 | meta.Session().commit() |
|
270 | meta.Session().commit() | |
270 |
|
271 | |||
271 | pre_cached_tip = [repo.get_api_data()['last_changeset']['short_id'] for repo in db.Repository.query().filter(db.Repository.repo_name == repo_name)] |
|
272 | pre_cached_tip = [repo.get_api_data()['last_changeset']['short_id'] for repo in db.Repository.query().filter(db.Repository.repo_name == repo_name)] | |
272 |
|
273 | |||
273 | id_, params = _build_data(self.apikey, 'pull', |
|
274 | id_, params = _build_data(self.apikey, 'pull', | |
274 | repoid=repo_name,) |
|
275 | repoid=repo_name,) | |
275 | response = api_call(self, params) |
|
276 | response = api_call(self, params) | |
276 |
|
277 | |||
277 | expected = {'msg': 'Pulled from `%s`' % repo_name, |
|
278 | expected = {'msg': 'Pulled from `%s`' % repo_name, | |
278 | 'repository': repo_name} |
|
279 | 'repository': repo_name} | |
279 | self._compare_ok(id_, expected, given=response.body) |
|
280 | self._compare_ok(id_, expected, given=response.body) | |
280 |
|
281 | |||
281 | post_cached_tip = [repo.get_api_data()['last_changeset']['short_id'] for repo in db.Repository.query().filter(db.Repository.repo_name == repo_name)] |
|
282 | post_cached_tip = [repo.get_api_data()['last_changeset']['short_id'] for repo in db.Repository.query().filter(db.Repository.repo_name == repo_name)] | |
282 |
|
283 | |||
283 | fixture.destroy_repo(repo_name) |
|
284 | fixture.destroy_repo(repo_name) | |
284 |
|
285 | |||
285 | assert pre_cached_tip != post_cached_tip |
|
286 | assert pre_cached_tip != post_cached_tip | |
286 |
|
287 | |||
287 | def test_api_pull_fork(self): |
|
288 | def test_api_pull_fork(self): | |
288 | fork_name = 'fork' |
|
289 | fork_name = 'fork' | |
289 | fixture.create_fork(self.REPO, fork_name) |
|
290 | fixture.create_fork(self.REPO, fork_name) | |
290 | id_, params = _build_data(self.apikey, 'pull', |
|
291 | id_, params = _build_data(self.apikey, 'pull', | |
291 | repoid=fork_name,) |
|
292 | repoid=fork_name,) | |
292 | response = api_call(self, params) |
|
293 | response = api_call(self, params) | |
293 |
|
294 | |||
294 | expected = {'msg': 'Pulled from `%s`' % fork_name, |
|
295 | expected = {'msg': 'Pulled from `%s`' % fork_name, | |
295 | 'repository': fork_name} |
|
296 | 'repository': fork_name} | |
296 | self._compare_ok(id_, expected, given=response.body) |
|
297 | self._compare_ok(id_, expected, given=response.body) | |
297 |
|
298 | |||
298 | fixture.destroy_repo(fork_name) |
|
299 | fixture.destroy_repo(fork_name) | |
299 |
|
300 | |||
300 | def test_api_pull_error_no_remote_no_fork(self): |
|
301 | def test_api_pull_error_no_remote_no_fork(self): | |
301 | # should fail because no clone_uri is set |
|
302 | # should fail because no clone_uri is set | |
302 | id_, params = _build_data(self.apikey, 'pull', |
|
303 | id_, params = _build_data(self.apikey, 'pull', | |
303 | repoid=self.REPO, ) |
|
304 | repoid=self.REPO, ) | |
304 | response = api_call(self, params) |
|
305 | response = api_call(self, params) | |
305 |
|
306 | |||
306 | expected = 'Unable to pull changes from `%s`' % self.REPO |
|
307 | expected = 'Unable to pull changes from `%s`' % self.REPO | |
307 | self._compare_error(id_, expected, given=response.body) |
|
308 | self._compare_error(id_, expected, given=response.body) | |
308 |
|
309 | |||
309 | def test_api_pull_custom_remote(self): |
|
310 | def test_api_pull_custom_remote(self): | |
310 | repo_name = 'test_pull_custom_remote' |
|
311 | repo_name = 'test_pull_custom_remote' | |
311 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) |
|
312 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) | |
312 |
|
313 | |||
313 | custom_remote_path = os.path.join(db.Ui.get_by_key('paths', '/').ui_value, self.REPO) |
|
314 | custom_remote_path = os.path.join(db.Ui.get_by_key('paths', '/').ui_value, self.REPO) | |
314 |
|
315 | |||
315 | id_, params = _build_data(self.apikey, 'pull', |
|
316 | id_, params = _build_data(self.apikey, 'pull', | |
316 | repoid=repo_name, |
|
317 | repoid=repo_name, | |
317 | clone_uri=custom_remote_path) |
|
318 | clone_uri=custom_remote_path) | |
318 | response = api_call(self, params) |
|
319 | response = api_call(self, params) | |
319 |
|
320 | |||
320 | expected = {'msg': 'Pulled from `%s`' % repo_name, |
|
321 | expected = {'msg': 'Pulled from `%s`' % repo_name, | |
321 | 'repository': repo_name} |
|
322 | 'repository': repo_name} | |
322 | self._compare_ok(id_, expected, given=response.body) |
|
323 | self._compare_ok(id_, expected, given=response.body) | |
323 |
|
324 | |||
324 | fixture.destroy_repo(repo_name) |
|
325 | fixture.destroy_repo(repo_name) | |
325 |
|
326 | |||
326 | def test_api_rescan_repos(self): |
|
327 | def test_api_rescan_repos(self): | |
327 | id_, params = _build_data(self.apikey, 'rescan_repos') |
|
328 | id_, params = _build_data(self.apikey, 'rescan_repos') | |
328 | response = api_call(self, params) |
|
329 | response = api_call(self, params) | |
329 |
|
330 | |||
330 | expected = {'added': [], 'removed': []} |
|
331 | expected = {'added': [], 'removed': []} | |
331 | self._compare_ok(id_, expected, given=response.body) |
|
332 | self._compare_ok(id_, expected, given=response.body) | |
332 |
|
333 | |||
333 | @mock.patch.object(ScmModel, 'repo_scan', raise_exception) |
|
334 | @mock.patch.object(ScmModel, 'repo_scan', raise_exception) | |
334 | def test_api_rescann_error(self): |
|
335 | def test_api_rescann_error(self): | |
335 | id_, params = _build_data(self.apikey, 'rescan_repos', ) |
|
336 | id_, params = _build_data(self.apikey, 'rescan_repos', ) | |
336 | response = api_call(self, params) |
|
337 | response = api_call(self, params) | |
337 |
|
338 | |||
338 | expected = 'Error occurred during rescan repositories action' |
|
339 | expected = 'Error occurred during rescan repositories action' | |
339 | self._compare_error(id_, expected, given=response.body) |
|
340 | self._compare_error(id_, expected, given=response.body) | |
340 |
|
341 | |||
341 | def test_api_create_existing_user(self): |
|
342 | def test_api_create_existing_user(self): | |
342 | id_, params = _build_data(self.apikey, 'create_user', |
|
343 | id_, params = _build_data(self.apikey, 'create_user', | |
343 | username=base.TEST_USER_ADMIN_LOGIN, |
|
344 | username=base.TEST_USER_ADMIN_LOGIN, | |
344 | email='test@example.com', |
|
345 | email='test@example.com', | |
345 | password='trololo') |
|
346 | password='trololo') | |
346 | response = api_call(self, params) |
|
347 | response = api_call(self, params) | |
347 |
|
348 | |||
348 | expected = "user `%s` already exist" % base.TEST_USER_ADMIN_LOGIN |
|
349 | expected = "user `%s` already exist" % base.TEST_USER_ADMIN_LOGIN | |
349 | self._compare_error(id_, expected, given=response.body) |
|
350 | self._compare_error(id_, expected, given=response.body) | |
350 |
|
351 | |||
351 | def test_api_create_user_with_existing_email(self): |
|
352 | def test_api_create_user_with_existing_email(self): | |
352 | id_, params = _build_data(self.apikey, 'create_user', |
|
353 | id_, params = _build_data(self.apikey, 'create_user', | |
353 | username=base.TEST_USER_ADMIN_LOGIN + 'new', |
|
354 | username=base.TEST_USER_ADMIN_LOGIN + 'new', | |
354 | email=base.TEST_USER_REGULAR_EMAIL, |
|
355 | email=base.TEST_USER_REGULAR_EMAIL, | |
355 | password='trololo') |
|
356 | password='trololo') | |
356 | response = api_call(self, params) |
|
357 | response = api_call(self, params) | |
357 |
|
358 | |||
358 | expected = "email `%s` already exist" % base.TEST_USER_REGULAR_EMAIL |
|
359 | expected = "email `%s` already exist" % base.TEST_USER_REGULAR_EMAIL | |
359 | self._compare_error(id_, expected, given=response.body) |
|
360 | self._compare_error(id_, expected, given=response.body) | |
360 |
|
361 | |||
361 | def test_api_create_user(self): |
|
362 | def test_api_create_user(self): | |
362 | username = 'test_new_api_user' |
|
363 | username = 'test_new_api_user' | |
363 | email = username + "@example.com" |
|
364 | email = username + "@example.com" | |
364 |
|
365 | |||
365 | id_, params = _build_data(self.apikey, 'create_user', |
|
366 | id_, params = _build_data(self.apikey, 'create_user', | |
366 | username=username, |
|
367 | username=username, | |
367 | email=email, |
|
368 | email=email, | |
368 | password='trololo') |
|
369 | password='trololo') | |
369 | response = api_call(self, params) |
|
370 | response = api_call(self, params) | |
370 |
|
371 | |||
371 | usr = db.User.get_by_username(username) |
|
372 | usr = db.User.get_by_username(username) | |
372 | ret = dict( |
|
373 | ret = dict( | |
373 | msg='created new user `%s`' % username, |
|
374 | msg='created new user `%s`' % username, | |
374 | user=jsonify(usr.get_api_data()) |
|
375 | user=jsonify(usr.get_api_data()) | |
375 | ) |
|
376 | ) | |
376 |
|
377 | |||
377 | try: |
|
378 | try: | |
378 | expected = ret |
|
379 | expected = ret | |
379 | self._compare_ok(id_, expected, given=response.body) |
|
380 | self._compare_ok(id_, expected, given=response.body) | |
380 | finally: |
|
381 | finally: | |
381 | fixture.destroy_user(usr.user_id) |
|
382 | fixture.destroy_user(usr.user_id) | |
382 |
|
383 | |||
383 | def test_api_create_user_without_password(self): |
|
384 | def test_api_create_user_without_password(self): | |
384 | username = 'test_new_api_user_passwordless' |
|
385 | username = 'test_new_api_user_passwordless' | |
385 | email = username + "@example.com" |
|
386 | email = username + "@example.com" | |
386 |
|
387 | |||
387 | id_, params = _build_data(self.apikey, 'create_user', |
|
388 | id_, params = _build_data(self.apikey, 'create_user', | |
388 | username=username, |
|
389 | username=username, | |
389 | email=email) |
|
390 | email=email) | |
390 | response = api_call(self, params) |
|
391 | response = api_call(self, params) | |
391 |
|
392 | |||
392 | usr = db.User.get_by_username(username) |
|
393 | usr = db.User.get_by_username(username) | |
393 | ret = dict( |
|
394 | ret = dict( | |
394 | msg='created new user `%s`' % username, |
|
395 | msg='created new user `%s`' % username, | |
395 | user=jsonify(usr.get_api_data()) |
|
396 | user=jsonify(usr.get_api_data()) | |
396 | ) |
|
397 | ) | |
397 | try: |
|
398 | try: | |
398 | expected = ret |
|
399 | expected = ret | |
399 | self._compare_ok(id_, expected, given=response.body) |
|
400 | self._compare_ok(id_, expected, given=response.body) | |
400 | finally: |
|
401 | finally: | |
401 | fixture.destroy_user(usr.user_id) |
|
402 | fixture.destroy_user(usr.user_id) | |
402 |
|
403 | |||
403 | def test_api_create_user_with_extern_name(self): |
|
404 | def test_api_create_user_with_extern_name(self): | |
404 | username = 'test_new_api_user_passwordless' |
|
405 | username = 'test_new_api_user_passwordless' | |
405 | email = username + "@example.com" |
|
406 | email = username + "@example.com" | |
406 |
|
407 | |||
407 | id_, params = _build_data(self.apikey, 'create_user', |
|
408 | id_, params = _build_data(self.apikey, 'create_user', | |
408 | username=username, |
|
409 | username=username, | |
409 | email=email, extern_name='internal') |
|
410 | email=email, extern_name='internal') | |
410 | response = api_call(self, params) |
|
411 | response = api_call(self, params) | |
411 |
|
412 | |||
412 | usr = db.User.get_by_username(username) |
|
413 | usr = db.User.get_by_username(username) | |
413 | ret = dict( |
|
414 | ret = dict( | |
414 | msg='created new user `%s`' % username, |
|
415 | msg='created new user `%s`' % username, | |
415 | user=jsonify(usr.get_api_data()) |
|
416 | user=jsonify(usr.get_api_data()) | |
416 | ) |
|
417 | ) | |
417 | try: |
|
418 | try: | |
418 | expected = ret |
|
419 | expected = ret | |
419 | self._compare_ok(id_, expected, given=response.body) |
|
420 | self._compare_ok(id_, expected, given=response.body) | |
420 | finally: |
|
421 | finally: | |
421 | fixture.destroy_user(usr.user_id) |
|
422 | fixture.destroy_user(usr.user_id) | |
422 |
|
423 | |||
423 | @mock.patch.object(UserModel, 'create_or_update', raise_exception) |
|
424 | @mock.patch.object(UserModel, 'create_or_update', raise_exception) | |
424 | def test_api_create_user_when_exception_happened(self): |
|
425 | def test_api_create_user_when_exception_happened(self): | |
425 |
|
426 | |||
426 | username = 'test_new_api_user' |
|
427 | username = 'test_new_api_user' | |
427 | email = username + "@example.com" |
|
428 | email = username + "@example.com" | |
428 |
|
429 | |||
429 | id_, params = _build_data(self.apikey, 'create_user', |
|
430 | id_, params = _build_data(self.apikey, 'create_user', | |
430 | username=username, |
|
431 | username=username, | |
431 | email=email, |
|
432 | email=email, | |
432 | password='trololo') |
|
433 | password='trololo') | |
433 | response = api_call(self, params) |
|
434 | response = api_call(self, params) | |
434 | expected = 'failed to create user `%s`' % username |
|
435 | expected = 'failed to create user `%s`' % username | |
435 | self._compare_error(id_, expected, given=response.body) |
|
436 | self._compare_error(id_, expected, given=response.body) | |
436 |
|
437 | |||
437 | def test_api_delete_user(self): |
|
438 | def test_api_delete_user(self): | |
438 | usr = UserModel().create_or_update(username='test_user', |
|
439 | usr = UserModel().create_or_update(username='test_user', | |
439 | password='qweqwe', |
|
440 | password='qweqwe', | |
440 | email='u232@example.com', |
|
441 | email='u232@example.com', | |
441 | firstname='u1', lastname='u1') |
|
442 | firstname='u1', lastname='u1') | |
442 | meta.Session().commit() |
|
443 | meta.Session().commit() | |
443 | username = usr.username |
|
444 | username = usr.username | |
444 | email = usr.email |
|
445 | email = usr.email | |
445 | usr_id = usr.user_id |
|
446 | usr_id = usr.user_id | |
446 | ## DELETE THIS USER NOW |
|
447 | ## DELETE THIS USER NOW | |
447 |
|
448 | |||
448 | id_, params = _build_data(self.apikey, 'delete_user', |
|
449 | id_, params = _build_data(self.apikey, 'delete_user', | |
449 | userid=username, ) |
|
450 | userid=username, ) | |
450 | response = api_call(self, params) |
|
451 | response = api_call(self, params) | |
451 |
|
452 | |||
452 | ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username), |
|
453 | ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username), | |
453 | 'user': None} |
|
454 | 'user': None} | |
454 | expected = ret |
|
455 | expected = ret | |
455 | self._compare_ok(id_, expected, given=response.body) |
|
456 | self._compare_ok(id_, expected, given=response.body) | |
456 |
|
457 | |||
457 | @mock.patch.object(UserModel, 'delete', raise_exception) |
|
458 | @mock.patch.object(UserModel, 'delete', raise_exception) | |
458 | def test_api_delete_user_when_exception_happened(self): |
|
459 | def test_api_delete_user_when_exception_happened(self): | |
459 | usr = UserModel().create_or_update(username='test_user', |
|
460 | usr = UserModel().create_or_update(username='test_user', | |
460 | password='qweqwe', |
|
461 | password='qweqwe', | |
461 | email='u232@example.com', |
|
462 | email='u232@example.com', | |
462 | firstname='u1', lastname='u1') |
|
463 | firstname='u1', lastname='u1') | |
463 | meta.Session().commit() |
|
464 | meta.Session().commit() | |
464 | username = usr.username |
|
465 | username = usr.username | |
465 |
|
466 | |||
466 | id_, params = _build_data(self.apikey, 'delete_user', |
|
467 | id_, params = _build_data(self.apikey, 'delete_user', | |
467 | userid=username, ) |
|
468 | userid=username, ) | |
468 | response = api_call(self, params) |
|
469 | response = api_call(self, params) | |
469 | ret = 'failed to delete user ID:%s %s' % (usr.user_id, |
|
470 | ret = 'failed to delete user ID:%s %s' % (usr.user_id, | |
470 | usr.username) |
|
471 | usr.username) | |
471 | expected = ret |
|
472 | expected = ret | |
472 | self._compare_error(id_, expected, given=response.body) |
|
473 | self._compare_error(id_, expected, given=response.body) | |
473 |
|
474 | |||
474 | @base.parametrize('name,expected', [ |
|
475 | @base.parametrize('name,expected', [ | |
475 | ('firstname', 'new_username'), |
|
476 | ('firstname', 'new_username'), | |
476 | ('lastname', 'new_username'), |
|
477 | ('lastname', 'new_username'), | |
477 | ('email', 'new_username'), |
|
478 | ('email', 'new_username'), | |
478 | ('admin', True), |
|
479 | ('admin', True), | |
479 | ('admin', False), |
|
480 | ('admin', False), | |
480 | ('extern_type', 'ldap'), |
|
481 | ('extern_type', 'ldap'), | |
481 | ('extern_type', None), |
|
482 | ('extern_type', None), | |
482 | ('extern_name', 'test'), |
|
483 | ('extern_name', 'test'), | |
483 | ('extern_name', None), |
|
484 | ('extern_name', None), | |
484 | ('active', False), |
|
485 | ('active', False), | |
485 | ('active', True), |
|
486 | ('active', True), | |
486 | ('password', 'newpass'), |
|
487 | ('password', 'newpass'), | |
487 | ]) |
|
488 | ]) | |
488 | def test_api_update_user(self, name, expected): |
|
489 | def test_api_update_user(self, name, expected): | |
489 | usr = db.User.get_by_username(self.TEST_USER_LOGIN) |
|
490 | usr = db.User.get_by_username(self.TEST_USER_LOGIN) | |
490 | kw = {name: expected, |
|
491 | kw = {name: expected, | |
491 | 'userid': usr.user_id} |
|
492 | 'userid': usr.user_id} | |
492 | id_, params = _build_data(self.apikey, 'update_user', **kw) |
|
493 | id_, params = _build_data(self.apikey, 'update_user', **kw) | |
493 | response = api_call(self, params) |
|
494 | response = api_call(self, params) | |
494 |
|
495 | |||
495 | ret = { |
|
496 | ret = { | |
496 | 'msg': 'updated user ID:%s %s' % ( |
|
497 | 'msg': 'updated user ID:%s %s' % ( | |
497 | usr.user_id, self.TEST_USER_LOGIN), |
|
498 | usr.user_id, self.TEST_USER_LOGIN), | |
498 | 'user': jsonify(db.User \ |
|
499 | 'user': jsonify(db.User \ | |
499 | .get_by_username(self.TEST_USER_LOGIN) \ |
|
500 | .get_by_username(self.TEST_USER_LOGIN) \ | |
500 | .get_api_data()) |
|
501 | .get_api_data()) | |
501 | } |
|
502 | } | |
502 |
|
503 | |||
503 | expected = ret |
|
504 | expected = ret | |
504 | self._compare_ok(id_, expected, given=response.body) |
|
505 | self._compare_ok(id_, expected, given=response.body) | |
505 |
|
506 | |||
506 | def test_api_update_user_no_changed_params(self): |
|
507 | def test_api_update_user_no_changed_params(self): | |
507 | usr = db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) |
|
508 | usr = db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) | |
508 | ret = jsonify(usr.get_api_data()) |
|
509 | ret = jsonify(usr.get_api_data()) | |
509 | id_, params = _build_data(self.apikey, 'update_user', |
|
510 | id_, params = _build_data(self.apikey, 'update_user', | |
510 | userid=base.TEST_USER_ADMIN_LOGIN) |
|
511 | userid=base.TEST_USER_ADMIN_LOGIN) | |
511 |
|
512 | |||
512 | response = api_call(self, params) |
|
513 | response = api_call(self, params) | |
513 | ret = { |
|
514 | ret = { | |
514 | 'msg': 'updated user ID:%s %s' % ( |
|
515 | 'msg': 'updated user ID:%s %s' % ( | |
515 | usr.user_id, base.TEST_USER_ADMIN_LOGIN), |
|
516 | usr.user_id, base.TEST_USER_ADMIN_LOGIN), | |
516 | 'user': ret |
|
517 | 'user': ret | |
517 | } |
|
518 | } | |
518 | expected = ret |
|
519 | expected = ret | |
519 | self._compare_ok(id_, expected, given=response.body) |
|
520 | self._compare_ok(id_, expected, given=response.body) | |
520 |
|
521 | |||
521 | def test_api_update_user_by_user_id(self): |
|
522 | def test_api_update_user_by_user_id(self): | |
522 | usr = db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) |
|
523 | usr = db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) | |
523 | ret = jsonify(usr.get_api_data()) |
|
524 | ret = jsonify(usr.get_api_data()) | |
524 | id_, params = _build_data(self.apikey, 'update_user', |
|
525 | id_, params = _build_data(self.apikey, 'update_user', | |
525 | userid=usr.user_id) |
|
526 | userid=usr.user_id) | |
526 |
|
527 | |||
527 | response = api_call(self, params) |
|
528 | response = api_call(self, params) | |
528 | ret = { |
|
529 | ret = { | |
529 | 'msg': 'updated user ID:%s %s' % ( |
|
530 | 'msg': 'updated user ID:%s %s' % ( | |
530 | usr.user_id, base.TEST_USER_ADMIN_LOGIN), |
|
531 | usr.user_id, base.TEST_USER_ADMIN_LOGIN), | |
531 | 'user': ret |
|
532 | 'user': ret | |
532 | } |
|
533 | } | |
533 | expected = ret |
|
534 | expected = ret | |
534 | self._compare_ok(id_, expected, given=response.body) |
|
535 | self._compare_ok(id_, expected, given=response.body) | |
535 |
|
536 | |||
536 | def test_api_update_user_default_user(self): |
|
537 | def test_api_update_user_default_user(self): | |
537 | usr = db.User.get_default_user() |
|
538 | usr = db.User.get_default_user() | |
538 | id_, params = _build_data(self.apikey, 'update_user', |
|
539 | id_, params = _build_data(self.apikey, 'update_user', | |
539 | userid=usr.user_id) |
|
540 | userid=usr.user_id) | |
540 |
|
541 | |||
541 | response = api_call(self, params) |
|
542 | response = api_call(self, params) | |
542 | expected = 'editing default user is forbidden' |
|
543 | expected = 'editing default user is forbidden' | |
543 | self._compare_error(id_, expected, given=response.body) |
|
544 | self._compare_error(id_, expected, given=response.body) | |
544 |
|
545 | |||
545 | @mock.patch.object(UserModel, 'update_user', raise_exception) |
|
546 | @mock.patch.object(UserModel, 'update_user', raise_exception) | |
546 | def test_api_update_user_when_exception_happens(self): |
|
547 | def test_api_update_user_when_exception_happens(self): | |
547 | usr = db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) |
|
548 | usr = db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) | |
548 | ret = jsonify(usr.get_api_data()) |
|
549 | ret = jsonify(usr.get_api_data()) | |
549 | id_, params = _build_data(self.apikey, 'update_user', |
|
550 | id_, params = _build_data(self.apikey, 'update_user', | |
550 | userid=usr.user_id) |
|
551 | userid=usr.user_id) | |
551 |
|
552 | |||
552 | response = api_call(self, params) |
|
553 | response = api_call(self, params) | |
553 | ret = 'failed to update user `%s`' % usr.user_id |
|
554 | ret = 'failed to update user `%s`' % usr.user_id | |
554 |
|
555 | |||
555 | expected = ret |
|
556 | expected = ret | |
556 | self._compare_error(id_, expected, given=response.body) |
|
557 | self._compare_error(id_, expected, given=response.body) | |
557 |
|
558 | |||
558 | def test_api_get_repo(self): |
|
559 | def test_api_get_repo(self): | |
559 | new_group = 'some_new_group' |
|
560 | new_group = 'some_new_group' | |
560 | make_user_group(new_group) |
|
561 | make_user_group(new_group) | |
561 | RepoModel().grant_user_group_permission(repo=self.REPO, |
|
562 | RepoModel().grant_user_group_permission(repo=self.REPO, | |
562 | group_name=new_group, |
|
563 | group_name=new_group, | |
563 | perm='repository.read') |
|
564 | perm='repository.read') | |
564 | meta.Session().commit() |
|
565 | meta.Session().commit() | |
565 | id_, params = _build_data(self.apikey, 'get_repo', |
|
566 | id_, params = _build_data(self.apikey, 'get_repo', | |
566 | repoid=self.REPO) |
|
567 | repoid=self.REPO) | |
567 | response = api_call(self, params) |
|
568 | response = api_call(self, params) | |
568 | assert "tags" not in response.json['result'] |
|
569 | assert "tags" not in response.json['result'] | |
569 | assert 'pull_requests' not in response.json['result'] |
|
570 | assert 'pull_requests' not in response.json['result'] | |
570 |
|
571 | |||
571 | repo = RepoModel().get_by_repo_name(self.REPO) |
|
572 | repo = RepoModel().get_by_repo_name(self.REPO) | |
572 | ret = repo.get_api_data() |
|
573 | ret = repo.get_api_data() | |
573 |
|
574 | |||
574 | members = [] |
|
575 | members = [] | |
575 | followers = [] |
|
576 | followers = [] | |
576 | for user in repo.repo_to_perm: |
|
577 | for user in repo.repo_to_perm: | |
577 | perm = user.permission.permission_name |
|
578 | perm = user.permission.permission_name | |
578 | user = user.user |
|
579 | user = user.user | |
579 | user_data = {'name': user.username, 'type': "user", |
|
580 | user_data = {'name': user.username, 'type': "user", | |
580 | 'permission': perm} |
|
581 | 'permission': perm} | |
581 | members.append(user_data) |
|
582 | members.append(user_data) | |
582 |
|
583 | |||
583 | for user_group in repo.users_group_to_perm: |
|
584 | for user_group in repo.users_group_to_perm: | |
584 | perm = user_group.permission.permission_name |
|
585 | perm = user_group.permission.permission_name | |
585 | user_group = user_group.users_group |
|
586 | user_group = user_group.users_group | |
586 | user_group_data = {'name': user_group.users_group_name, |
|
587 | user_group_data = {'name': user_group.users_group_name, | |
587 | 'type': "user_group", 'permission': perm} |
|
588 | 'type': "user_group", 'permission': perm} | |
588 | members.append(user_group_data) |
|
589 | members.append(user_group_data) | |
589 |
|
590 | |||
590 | for user in repo.followers: |
|
591 | for user in repo.followers: | |
591 | followers.append(user.user.get_api_data()) |
|
592 | followers.append(user.user.get_api_data()) | |
592 |
|
593 | |||
593 | ret['members'] = members |
|
594 | ret['members'] = members | |
594 | ret['followers'] = followers |
|
595 | ret['followers'] = followers | |
595 |
|
596 | |||
596 | expected = ret |
|
597 | expected = ret | |
597 | self._compare_ok(id_, expected, given=response.body) |
|
598 | self._compare_ok(id_, expected, given=response.body) | |
598 | fixture.destroy_user_group(new_group) |
|
599 | fixture.destroy_user_group(new_group) | |
599 |
|
600 | |||
600 | id_, params = _build_data(self.apikey, 'get_repo', repoid=self.REPO, |
|
601 | id_, params = _build_data(self.apikey, 'get_repo', repoid=self.REPO, | |
601 | with_revision_names=True, |
|
602 | with_revision_names=True, | |
602 | with_pullrequests=True) |
|
603 | with_pullrequests=True) | |
603 | response = api_call(self, params) |
|
604 | response = api_call(self, params) | |
604 | assert "v0.2.0" in response.json['result']['tags'] |
|
605 | assert "v0.2.0" in response.json['result']['tags'] | |
605 | assert 'pull_requests' in response.json['result'] |
|
606 | assert 'pull_requests' in response.json['result'] | |
606 |
|
607 | |||
607 | @base.parametrize('grant_perm', [ |
|
608 | @base.parametrize('grant_perm', [ | |
608 | ('repository.admin'), |
|
609 | ('repository.admin'), | |
609 | ('repository.write'), |
|
610 | ('repository.write'), | |
610 | ('repository.read'), |
|
611 | ('repository.read'), | |
611 | ]) |
|
612 | ]) | |
612 | def test_api_get_repo_by_non_admin(self, grant_perm): |
|
613 | def test_api_get_repo_by_non_admin(self, grant_perm): | |
613 | RepoModel().grant_user_permission(repo=self.REPO, |
|
614 | RepoModel().grant_user_permission(repo=self.REPO, | |
614 | user=self.TEST_USER_LOGIN, |
|
615 | user=self.TEST_USER_LOGIN, | |
615 | perm=grant_perm) |
|
616 | perm=grant_perm) | |
616 | meta.Session().commit() |
|
617 | meta.Session().commit() | |
617 | id_, params = _build_data(self.apikey_regular, 'get_repo', |
|
618 | id_, params = _build_data(self.apikey_regular, 'get_repo', | |
618 | repoid=self.REPO) |
|
619 | repoid=self.REPO) | |
619 | response = api_call(self, params) |
|
620 | response = api_call(self, params) | |
620 |
|
621 | |||
621 | repo = RepoModel().get_by_repo_name(self.REPO) |
|
622 | repo = RepoModel().get_by_repo_name(self.REPO) | |
622 | assert len(repo.repo_to_perm) >= 2 # make sure we actually are testing something - probably the default 2 permissions, possibly more |
|
623 | assert len(repo.repo_to_perm) >= 2 # make sure we actually are testing something - probably the default 2 permissions, possibly more | |
623 |
|
624 | |||
624 | expected = repo.get_api_data() |
|
625 | expected = repo.get_api_data() | |
625 |
|
626 | |||
626 | members = [] |
|
627 | members = [] | |
627 | for user in repo.repo_to_perm: |
|
628 | for user in repo.repo_to_perm: | |
628 | perm = user.permission.permission_name |
|
629 | perm = user.permission.permission_name | |
629 | user_obj = user.user |
|
630 | user_obj = user.user | |
630 | user_data = {'name': user_obj.username, 'type': "user", |
|
631 | user_data = {'name': user_obj.username, 'type': "user", | |
631 | 'permission': perm} |
|
632 | 'permission': perm} | |
632 | members.append(user_data) |
|
633 | members.append(user_data) | |
633 | for user_group in repo.users_group_to_perm: |
|
634 | for user_group in repo.users_group_to_perm: | |
634 | perm = user_group.permission.permission_name |
|
635 | perm = user_group.permission.permission_name | |
635 | user_group_obj = user_group.users_group |
|
636 | user_group_obj = user_group.users_group | |
636 | user_group_data = {'name': user_group_obj.users_group_name, |
|
637 | user_group_data = {'name': user_group_obj.users_group_name, | |
637 | 'type': "user_group", 'permission': perm} |
|
638 | 'type': "user_group", 'permission': perm} | |
638 | members.append(user_group_data) |
|
639 | members.append(user_group_data) | |
639 | expected['members'] = members |
|
640 | expected['members'] = members | |
640 |
|
641 | |||
641 | followers = [] |
|
642 | followers = [] | |
642 |
|
643 | |||
643 | for user in repo.followers: |
|
644 | for user in repo.followers: | |
644 | followers.append(user.user.get_api_data()) |
|
645 | followers.append(user.user.get_api_data()) | |
645 |
|
646 | |||
646 | expected['followers'] = followers |
|
647 | expected['followers'] = followers | |
647 |
|
648 | |||
648 | try: |
|
649 | try: | |
649 | self._compare_ok(id_, expected, given=response.body) |
|
650 | self._compare_ok(id_, expected, given=response.body) | |
650 | finally: |
|
651 | finally: | |
651 | RepoModel().revoke_user_permission(self.REPO, self.TEST_USER_LOGIN) |
|
652 | RepoModel().revoke_user_permission(self.REPO, self.TEST_USER_LOGIN) | |
652 |
|
653 | |||
653 | def test_api_get_repo_by_non_admin_no_permission_to_repo(self): |
|
654 | def test_api_get_repo_by_non_admin_no_permission_to_repo(self): | |
654 | RepoModel().grant_user_permission(repo=self.REPO, |
|
655 | RepoModel().grant_user_permission(repo=self.REPO, | |
655 | user=db.User.DEFAULT_USER_NAME, |
|
656 | user=db.User.DEFAULT_USER_NAME, | |
656 | perm='repository.none') |
|
657 | perm='repository.none') | |
657 | try: |
|
658 | try: | |
658 | RepoModel().grant_user_permission(repo=self.REPO, |
|
659 | RepoModel().grant_user_permission(repo=self.REPO, | |
659 | user=self.TEST_USER_LOGIN, |
|
660 | user=self.TEST_USER_LOGIN, | |
660 | perm='repository.none') |
|
661 | perm='repository.none') | |
661 |
|
662 | |||
662 | id_, params = _build_data(self.apikey_regular, 'get_repo', |
|
663 | id_, params = _build_data(self.apikey_regular, 'get_repo', | |
663 | repoid=self.REPO) |
|
664 | repoid=self.REPO) | |
664 | response = api_call(self, params) |
|
665 | response = api_call(self, params) | |
665 |
|
666 | |||
666 | expected = 'repository `%s` does not exist' % (self.REPO) |
|
667 | expected = 'repository `%s` does not exist' % (self.REPO) | |
667 | self._compare_error(id_, expected, given=response.body) |
|
668 | self._compare_error(id_, expected, given=response.body) | |
668 | finally: |
|
669 | finally: | |
669 | RepoModel().grant_user_permission(repo=self.REPO, |
|
670 | RepoModel().grant_user_permission(repo=self.REPO, | |
670 | user=db.User.DEFAULT_USER_NAME, |
|
671 | user=db.User.DEFAULT_USER_NAME, | |
671 | perm='repository.read') |
|
672 | perm='repository.read') | |
672 |
|
673 | |||
673 | def test_api_get_repo_that_doesn_not_exist(self): |
|
674 | def test_api_get_repo_that_doesn_not_exist(self): | |
674 | id_, params = _build_data(self.apikey, 'get_repo', |
|
675 | id_, params = _build_data(self.apikey, 'get_repo', | |
675 | repoid='no-such-repo') |
|
676 | repoid='no-such-repo') | |
676 | response = api_call(self, params) |
|
677 | response = api_call(self, params) | |
677 |
|
678 | |||
678 | ret = 'repository `%s` does not exist' % 'no-such-repo' |
|
679 | ret = 'repository `%s` does not exist' % 'no-such-repo' | |
679 | expected = ret |
|
680 | expected = ret | |
680 | self._compare_error(id_, expected, given=response.body) |
|
681 | self._compare_error(id_, expected, given=response.body) | |
681 |
|
682 | |||
682 | def test_api_get_repos(self): |
|
683 | def test_api_get_repos(self): | |
683 | id_, params = _build_data(self.apikey, 'get_repos') |
|
684 | id_, params = _build_data(self.apikey, 'get_repos') | |
684 | response = api_call(self, params) |
|
685 | response = api_call(self, params) | |
685 |
|
686 | |||
686 | expected = jsonify([ |
|
687 | expected = jsonify([ | |
687 | repo.get_api_data() |
|
688 | repo.get_api_data() | |
688 | for repo in db.Repository.query() |
|
689 | for repo in db.Repository.query() | |
689 | ]) |
|
690 | ]) | |
690 |
|
691 | |||
691 | self._compare_ok(id_, expected, given=response.body) |
|
692 | self._compare_ok(id_, expected, given=response.body) | |
692 |
|
693 | |||
693 | def test_api_get_repos_non_admin(self): |
|
694 | def test_api_get_repos_non_admin(self): | |
694 | id_, params = _build_data(self.apikey_regular, 'get_repos') |
|
695 | id_, params = _build_data(self.apikey_regular, 'get_repos') | |
695 | response = api_call(self, params) |
|
696 | response = api_call(self, params) | |
696 |
|
697 | |||
697 | expected = jsonify([ |
|
698 | expected = jsonify([ | |
698 | repo.get_api_data() |
|
699 | repo.get_api_data() | |
699 | for repo in AuthUser(dbuser=db.User.get_by_username(self.TEST_USER_LOGIN)).get_all_user_repos() |
|
700 | for repo in AuthUser(dbuser=db.User.get_by_username(self.TEST_USER_LOGIN)).get_all_user_repos() | |
700 | ]) |
|
701 | ]) | |
701 |
|
702 | |||
702 | self._compare_ok(id_, expected, given=response.body) |
|
703 | self._compare_ok(id_, expected, given=response.body) | |
703 |
|
704 | |||
704 | @base.parametrize('name,ret_type', [ |
|
705 | @base.parametrize('name,ret_type', [ | |
705 | ('all', 'all'), |
|
706 | ('all', 'all'), | |
706 | ('dirs', 'dirs'), |
|
707 | ('dirs', 'dirs'), | |
707 | ('files', 'files'), |
|
708 | ('files', 'files'), | |
708 | ]) |
|
709 | ]) | |
709 | def test_api_get_repo_nodes(self, name, ret_type): |
|
710 | def test_api_get_repo_nodes(self, name, ret_type): | |
710 | rev = 'tip' |
|
711 | rev = 'tip' | |
711 | path = '/' |
|
712 | path = '/' | |
712 | id_, params = _build_data(self.apikey, 'get_repo_nodes', |
|
713 | id_, params = _build_data(self.apikey, 'get_repo_nodes', | |
713 | repoid=self.REPO, revision=rev, |
|
714 | repoid=self.REPO, revision=rev, | |
714 | root_path=path, |
|
715 | root_path=path, | |
715 | ret_type=ret_type) |
|
716 | ret_type=ret_type) | |
716 | response = api_call(self, params) |
|
717 | response = api_call(self, params) | |
717 |
|
718 | |||
718 | # we don't the actual return types here since it's tested somewhere |
|
719 | # we don't the actual return types here since it's tested somewhere | |
719 | # else |
|
720 | # else | |
720 | expected = response.json['result'] |
|
721 | expected = response.json['result'] | |
721 | self._compare_ok(id_, expected, given=response.body) |
|
722 | self._compare_ok(id_, expected, given=response.body) | |
722 |
|
723 | |||
723 | def test_api_get_repo_nodes_bad_revisions(self): |
|
724 | def test_api_get_repo_nodes_bad_revisions(self): | |
724 | rev = 'i-dont-exist' |
|
725 | rev = 'i-dont-exist' | |
725 | path = '/' |
|
726 | path = '/' | |
726 | id_, params = _build_data(self.apikey, 'get_repo_nodes', |
|
727 | id_, params = _build_data(self.apikey, 'get_repo_nodes', | |
727 | repoid=self.REPO, revision=rev, |
|
728 | repoid=self.REPO, revision=rev, | |
728 | root_path=path, ) |
|
729 | root_path=path, ) | |
729 | response = api_call(self, params) |
|
730 | response = api_call(self, params) | |
730 |
|
731 | |||
731 | expected = 'failed to get repo: `%s` nodes' % self.REPO |
|
732 | expected = 'failed to get repo: `%s` nodes' % self.REPO | |
732 | self._compare_error(id_, expected, given=response.body) |
|
733 | self._compare_error(id_, expected, given=response.body) | |
733 |
|
734 | |||
734 | def test_api_get_repo_nodes_bad_path(self): |
|
735 | def test_api_get_repo_nodes_bad_path(self): | |
735 | rev = 'tip' |
|
736 | rev = 'tip' | |
736 | path = '/idontexits' |
|
737 | path = '/idontexits' | |
737 | id_, params = _build_data(self.apikey, 'get_repo_nodes', |
|
738 | id_, params = _build_data(self.apikey, 'get_repo_nodes', | |
738 | repoid=self.REPO, revision=rev, |
|
739 | repoid=self.REPO, revision=rev, | |
739 | root_path=path, ) |
|
740 | root_path=path, ) | |
740 | response = api_call(self, params) |
|
741 | response = api_call(self, params) | |
741 |
|
742 | |||
742 | expected = 'failed to get repo: `%s` nodes' % self.REPO |
|
743 | expected = 'failed to get repo: `%s` nodes' % self.REPO | |
743 | self._compare_error(id_, expected, given=response.body) |
|
744 | self._compare_error(id_, expected, given=response.body) | |
744 |
|
745 | |||
745 | def test_api_get_repo_nodes_bad_ret_type(self): |
|
746 | def test_api_get_repo_nodes_bad_ret_type(self): | |
746 | rev = 'tip' |
|
747 | rev = 'tip' | |
747 | path = '/' |
|
748 | path = '/' | |
748 | ret_type = 'error' |
|
749 | ret_type = 'error' | |
749 | id_, params = _build_data(self.apikey, 'get_repo_nodes', |
|
750 | id_, params = _build_data(self.apikey, 'get_repo_nodes', | |
750 | repoid=self.REPO, revision=rev, |
|
751 | repoid=self.REPO, revision=rev, | |
751 | root_path=path, |
|
752 | root_path=path, | |
752 | ret_type=ret_type) |
|
753 | ret_type=ret_type) | |
753 | response = api_call(self, params) |
|
754 | response = api_call(self, params) | |
754 |
|
755 | |||
755 | expected = ('ret_type must be one of %s' |
|
756 | expected = ('ret_type must be one of %s' | |
756 | % (','.join(sorted(['files', 'dirs', 'all'])))) |
|
757 | % (','.join(sorted(['files', 'dirs', 'all'])))) | |
757 | self._compare_error(id_, expected, given=response.body) |
|
758 | self._compare_error(id_, expected, given=response.body) | |
758 |
|
759 | |||
759 | @base.parametrize('name,ret_type,grant_perm', [ |
|
760 | @base.parametrize('name,ret_type,grant_perm', [ | |
760 | ('all', 'all', 'repository.write'), |
|
761 | ('all', 'all', 'repository.write'), | |
761 | ('dirs', 'dirs', 'repository.admin'), |
|
762 | ('dirs', 'dirs', 'repository.admin'), | |
762 | ('files', 'files', 'repository.read'), |
|
763 | ('files', 'files', 'repository.read'), | |
763 | ]) |
|
764 | ]) | |
764 | def test_api_get_repo_nodes_by_regular_user(self, name, ret_type, grant_perm): |
|
765 | def test_api_get_repo_nodes_by_regular_user(self, name, ret_type, grant_perm): | |
765 | RepoModel().grant_user_permission(repo=self.REPO, |
|
766 | RepoModel().grant_user_permission(repo=self.REPO, | |
766 | user=self.TEST_USER_LOGIN, |
|
767 | user=self.TEST_USER_LOGIN, | |
767 | perm=grant_perm) |
|
768 | perm=grant_perm) | |
768 | meta.Session().commit() |
|
769 | meta.Session().commit() | |
769 |
|
770 | |||
770 | rev = 'tip' |
|
771 | rev = 'tip' | |
771 | path = '/' |
|
772 | path = '/' | |
772 | id_, params = _build_data(self.apikey_regular, 'get_repo_nodes', |
|
773 | id_, params = _build_data(self.apikey_regular, 'get_repo_nodes', | |
773 | repoid=self.REPO, revision=rev, |
|
774 | repoid=self.REPO, revision=rev, | |
774 | root_path=path, |
|
775 | root_path=path, | |
775 | ret_type=ret_type) |
|
776 | ret_type=ret_type) | |
776 | response = api_call(self, params) |
|
777 | response = api_call(self, params) | |
777 |
|
778 | |||
778 | # we don't the actual return types here since it's tested somewhere |
|
779 | # we don't the actual return types here since it's tested somewhere | |
779 | # else |
|
780 | # else | |
780 | expected = response.json['result'] |
|
781 | expected = response.json['result'] | |
781 | try: |
|
782 | try: | |
782 | self._compare_ok(id_, expected, given=response.body) |
|
783 | self._compare_ok(id_, expected, given=response.body) | |
783 | finally: |
|
784 | finally: | |
784 | RepoModel().revoke_user_permission(self.REPO, self.TEST_USER_LOGIN) |
|
785 | RepoModel().revoke_user_permission(self.REPO, self.TEST_USER_LOGIN) | |
785 |
|
786 | |||
786 | def test_api_create_repo(self): |
|
787 | def test_api_create_repo(self): | |
787 | repo_name = 'api-repo' |
|
788 | repo_name = 'api-repo' | |
788 | id_, params = _build_data(self.apikey, 'create_repo', |
|
789 | id_, params = _build_data(self.apikey, 'create_repo', | |
789 | repo_name=repo_name, |
|
790 | repo_name=repo_name, | |
790 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
791 | owner=base.TEST_USER_ADMIN_LOGIN, | |
791 | repo_type=self.REPO_TYPE, |
|
792 | repo_type=self.REPO_TYPE, | |
792 | ) |
|
793 | ) | |
793 | response = api_call(self, params) |
|
794 | response = api_call(self, params) | |
794 |
|
795 | |||
795 | repo = RepoModel().get_by_repo_name(repo_name) |
|
796 | repo = RepoModel().get_by_repo_name(repo_name) | |
796 | assert repo is not None |
|
797 | assert repo is not None | |
797 | ret = { |
|
798 | ret = { | |
798 | 'msg': 'Created new repository `%s`' % repo_name, |
|
799 | 'msg': 'Created new repository `%s`' % repo_name, | |
799 | 'success': True, |
|
800 | 'success': True, | |
800 | } |
|
801 | } | |
801 | expected = ret |
|
802 | expected = ret | |
802 | self._compare_ok(id_, expected, given=response.body) |
|
803 | self._compare_ok(id_, expected, given=response.body) | |
803 | fixture.destroy_repo(repo_name) |
|
804 | fixture.destroy_repo(repo_name) | |
804 |
|
805 | |||
805 | @base.parametrize('repo_name', [ |
|
806 | @base.parametrize('repo_name', [ | |
806 | '', |
|
807 | '', | |
807 | '.', |
|
808 | '.', | |
808 | '..', |
|
809 | '..', | |
809 | ':', |
|
810 | ':', | |
810 | '/', |
|
811 | '/', | |
811 | '<test>', |
|
812 | '<test>', | |
812 | ]) |
|
813 | ]) | |
813 | def test_api_create_repo_bad_names(self, repo_name): |
|
814 | def test_api_create_repo_bad_names(self, repo_name): | |
814 | id_, params = _build_data(self.apikey, 'create_repo', |
|
815 | id_, params = _build_data(self.apikey, 'create_repo', | |
815 | repo_name=repo_name, |
|
816 | repo_name=repo_name, | |
816 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
817 | owner=base.TEST_USER_ADMIN_LOGIN, | |
817 | repo_type=self.REPO_TYPE, |
|
818 | repo_type=self.REPO_TYPE, | |
818 | ) |
|
819 | ) | |
819 | response = api_call(self, params) |
|
820 | response = api_call(self, params) | |
820 | if repo_name == '/': |
|
821 | if repo_name == '/': | |
821 | expected = "repo group `` not found" |
|
822 | expected = "repo group `` not found" | |
822 | self._compare_error(id_, expected, given=response.body) |
|
823 | self._compare_error(id_, expected, given=response.body) | |
823 | else: |
|
824 | else: | |
824 | expected = "failed to create repository `%s`" % repo_name |
|
825 | expected = "failed to create repository `%s`" % repo_name | |
825 | self._compare_error(id_, expected, given=response.body) |
|
826 | self._compare_error(id_, expected, given=response.body) | |
826 | fixture.destroy_repo(repo_name) |
|
827 | fixture.destroy_repo(repo_name) | |
827 |
|
828 | |||
828 | def test_api_create_repo_clone_uri_local(self): |
|
829 | def test_api_create_repo_clone_uri_local(self): | |
829 | # cloning from local repos was a mis-feature - it would bypass access control |
|
830 | # cloning from local repos was a mis-feature - it would bypass access control | |
830 | # TODO: introduce other test coverage of actual remote cloning |
|
831 | # TODO: introduce other test coverage of actual remote cloning | |
831 | clone_uri = os.path.join(base.TESTS_TMP_PATH, self.REPO) |
|
832 | clone_uri = os.path.join(base.TESTS_TMP_PATH, self.REPO) | |
832 | repo_name = 'api-repo' |
|
833 | repo_name = 'api-repo' | |
833 | id_, params = _build_data(self.apikey, 'create_repo', |
|
834 | id_, params = _build_data(self.apikey, 'create_repo', | |
834 | repo_name=repo_name, |
|
835 | repo_name=repo_name, | |
835 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
836 | owner=base.TEST_USER_ADMIN_LOGIN, | |
836 | repo_type=self.REPO_TYPE, |
|
837 | repo_type=self.REPO_TYPE, | |
837 | clone_uri=clone_uri, |
|
838 | clone_uri=clone_uri, | |
838 | ) |
|
839 | ) | |
839 | response = api_call(self, params) |
|
840 | response = api_call(self, params) | |
840 | expected = "failed to create repository `%s`" % repo_name |
|
841 | expected = "failed to create repository `%s`" % repo_name | |
841 | self._compare_error(id_, expected, given=response.body) |
|
842 | self._compare_error(id_, expected, given=response.body) | |
842 | fixture.destroy_repo(repo_name) |
|
843 | fixture.destroy_repo(repo_name) | |
843 |
|
844 | |||
844 | def test_api_create_repo_and_repo_group(self): |
|
845 | def test_api_create_repo_and_repo_group(self): | |
845 | repo_group_name = 'my_gr' |
|
846 | repo_group_name = 'my_gr' | |
846 | repo_name = '%s/api-repo' % repo_group_name |
|
847 | repo_name = '%s/api-repo' % repo_group_name | |
847 |
|
848 | |||
848 | # repo creation can no longer also create repo group |
|
849 | # repo creation can no longer also create repo group | |
849 | id_, params = _build_data(self.apikey, 'create_repo', |
|
850 | id_, params = _build_data(self.apikey, 'create_repo', | |
850 | repo_name=repo_name, |
|
851 | repo_name=repo_name, | |
851 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
852 | owner=base.TEST_USER_ADMIN_LOGIN, | |
852 | repo_type=self.REPO_TYPE,) |
|
853 | repo_type=self.REPO_TYPE,) | |
853 | response = api_call(self, params) |
|
854 | response = api_call(self, params) | |
854 | expected = 'repo group `%s` not found' % repo_group_name |
|
855 | expected = 'repo group `%s` not found' % repo_group_name | |
855 | self._compare_error(id_, expected, given=response.body) |
|
856 | self._compare_error(id_, expected, given=response.body) | |
856 | assert RepoModel().get_by_repo_name(repo_name) is None |
|
857 | assert RepoModel().get_by_repo_name(repo_name) is None | |
857 |
|
858 | |||
858 | # create group before creating repo |
|
859 | # create group before creating repo | |
859 | rg = fixture.create_repo_group(repo_group_name) |
|
860 | rg = fixture.create_repo_group(repo_group_name) | |
860 | meta.Session().commit() |
|
861 | meta.Session().commit() | |
861 |
|
862 | |||
862 | id_, params = _build_data(self.apikey, 'create_repo', |
|
863 | id_, params = _build_data(self.apikey, 'create_repo', | |
863 | repo_name=repo_name, |
|
864 | repo_name=repo_name, | |
864 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
865 | owner=base.TEST_USER_ADMIN_LOGIN, | |
865 | repo_type=self.REPO_TYPE,) |
|
866 | repo_type=self.REPO_TYPE,) | |
866 | response = api_call(self, params) |
|
867 | response = api_call(self, params) | |
867 | expected = { |
|
868 | expected = { | |
868 | 'msg': 'Created new repository `%s`' % repo_name, |
|
869 | 'msg': 'Created new repository `%s`' % repo_name, | |
869 | 'success': True, |
|
870 | 'success': True, | |
870 | } |
|
871 | } | |
871 | self._compare_ok(id_, expected, given=response.body) |
|
872 | self._compare_ok(id_, expected, given=response.body) | |
872 | repo = RepoModel().get_by_repo_name(repo_name) |
|
873 | repo = RepoModel().get_by_repo_name(repo_name) | |
873 | assert repo is not None |
|
874 | assert repo is not None | |
874 |
|
875 | |||
875 | fixture.destroy_repo(repo_name) |
|
876 | fixture.destroy_repo(repo_name) | |
876 | fixture.destroy_repo_group(repo_group_name) |
|
877 | fixture.destroy_repo_group(repo_group_name) | |
877 |
|
878 | |||
878 | def test_api_create_repo_in_repo_group_without_permission(self): |
|
879 | def test_api_create_repo_in_repo_group_without_permission(self): | |
879 | repo_group_basename = 'api-repo-repo' |
|
880 | repo_group_basename = 'api-repo-repo' | |
880 | repo_group_name = '%s/%s' % (TEST_REPO_GROUP, repo_group_basename) |
|
881 | repo_group_name = '%s/%s' % (TEST_REPO_GROUP, repo_group_basename) | |
881 | repo_name = '%s/api-repo' % repo_group_name |
|
882 | repo_name = '%s/api-repo' % repo_group_name | |
882 |
|
883 | |||
883 | top_group = db.RepoGroup.get_by_group_name(TEST_REPO_GROUP) |
|
884 | top_group = db.RepoGroup.get_by_group_name(TEST_REPO_GROUP) | |
884 | assert top_group |
|
885 | assert top_group | |
885 | rg = fixture.create_repo_group(repo_group_basename, parent_group_id=top_group) |
|
886 | rg = fixture.create_repo_group(repo_group_basename, parent_group_id=top_group) | |
886 | meta.Session().commit() |
|
887 | meta.Session().commit() | |
887 | RepoGroupModel().grant_user_permission(repo_group_name, |
|
888 | RepoGroupModel().grant_user_permission(repo_group_name, | |
888 | self.TEST_USER_LOGIN, |
|
889 | self.TEST_USER_LOGIN, | |
889 | 'group.none') |
|
890 | 'group.none') | |
890 | meta.Session().commit() |
|
891 | meta.Session().commit() | |
891 |
|
892 | |||
892 | id_, params = _build_data(self.apikey_regular, 'create_repo', |
|
893 | id_, params = _build_data(self.apikey_regular, 'create_repo', | |
893 | repo_name=repo_name, |
|
894 | repo_name=repo_name, | |
894 | repo_type=self.REPO_TYPE, |
|
895 | repo_type=self.REPO_TYPE, | |
895 | ) |
|
896 | ) | |
896 | response = api_call(self, params) |
|
897 | response = api_call(self, params) | |
897 |
|
898 | |||
898 | # API access control match Web access control: |
|
899 | # API access control match Web access control: | |
899 | expected = 'no permission to create repo in test_repo_group/api-repo-repo' |
|
900 | expected = 'no permission to create repo in test_repo_group/api-repo-repo' | |
900 | self._compare_error(id_, expected, given=response.body) |
|
901 | self._compare_error(id_, expected, given=response.body) | |
901 |
|
902 | |||
902 | fixture.destroy_repo(repo_name) |
|
903 | fixture.destroy_repo(repo_name) | |
903 | fixture.destroy_repo_group(repo_group_name) |
|
904 | fixture.destroy_repo_group(repo_group_name) | |
904 |
|
905 | |||
905 | def test_api_create_repo_unknown_owner(self): |
|
906 | def test_api_create_repo_unknown_owner(self): | |
906 | repo_name = 'api-repo' |
|
907 | repo_name = 'api-repo' | |
907 | owner = 'i-dont-exist' |
|
908 | owner = 'i-dont-exist' | |
908 | id_, params = _build_data(self.apikey, 'create_repo', |
|
909 | id_, params = _build_data(self.apikey, 'create_repo', | |
909 | repo_name=repo_name, |
|
910 | repo_name=repo_name, | |
910 | owner=owner, |
|
911 | owner=owner, | |
911 | repo_type=self.REPO_TYPE, |
|
912 | repo_type=self.REPO_TYPE, | |
912 | ) |
|
913 | ) | |
913 | response = api_call(self, params) |
|
914 | response = api_call(self, params) | |
914 | expected = 'user `%s` does not exist' % owner |
|
915 | expected = 'user `%s` does not exist' % owner | |
915 | self._compare_error(id_, expected, given=response.body) |
|
916 | self._compare_error(id_, expected, given=response.body) | |
916 |
|
917 | |||
917 | def test_api_create_repo_dont_specify_owner(self): |
|
918 | def test_api_create_repo_dont_specify_owner(self): | |
918 | repo_name = 'api-repo' |
|
919 | repo_name = 'api-repo' | |
919 | owner = 'i-dont-exist' |
|
920 | owner = 'i-dont-exist' | |
920 | id_, params = _build_data(self.apikey, 'create_repo', |
|
921 | id_, params = _build_data(self.apikey, 'create_repo', | |
921 | repo_name=repo_name, |
|
922 | repo_name=repo_name, | |
922 | repo_type=self.REPO_TYPE, |
|
923 | repo_type=self.REPO_TYPE, | |
923 | ) |
|
924 | ) | |
924 | response = api_call(self, params) |
|
925 | response = api_call(self, params) | |
925 |
|
926 | |||
926 | repo = RepoModel().get_by_repo_name(repo_name) |
|
927 | repo = RepoModel().get_by_repo_name(repo_name) | |
927 | assert repo is not None |
|
928 | assert repo is not None | |
928 | ret = { |
|
929 | ret = { | |
929 | 'msg': 'Created new repository `%s`' % repo_name, |
|
930 | 'msg': 'Created new repository `%s`' % repo_name, | |
930 | 'success': True, |
|
931 | 'success': True, | |
931 | } |
|
932 | } | |
932 | expected = ret |
|
933 | expected = ret | |
933 | self._compare_ok(id_, expected, given=response.body) |
|
934 | self._compare_ok(id_, expected, given=response.body) | |
934 | fixture.destroy_repo(repo_name) |
|
935 | fixture.destroy_repo(repo_name) | |
935 |
|
936 | |||
936 | def test_api_create_repo_by_non_admin(self): |
|
937 | def test_api_create_repo_by_non_admin(self): | |
937 | repo_name = 'api-repo' |
|
938 | repo_name = 'api-repo' | |
938 | owner = 'i-dont-exist' |
|
939 | owner = 'i-dont-exist' | |
939 | id_, params = _build_data(self.apikey_regular, 'create_repo', |
|
940 | id_, params = _build_data(self.apikey_regular, 'create_repo', | |
940 | repo_name=repo_name, |
|
941 | repo_name=repo_name, | |
941 | repo_type=self.REPO_TYPE, |
|
942 | repo_type=self.REPO_TYPE, | |
942 | ) |
|
943 | ) | |
943 | response = api_call(self, params) |
|
944 | response = api_call(self, params) | |
944 |
|
945 | |||
945 | repo = RepoModel().get_by_repo_name(repo_name) |
|
946 | repo = RepoModel().get_by_repo_name(repo_name) | |
946 | assert repo is not None |
|
947 | assert repo is not None | |
947 | ret = { |
|
948 | ret = { | |
948 | 'msg': 'Created new repository `%s`' % repo_name, |
|
949 | 'msg': 'Created new repository `%s`' % repo_name, | |
949 | 'success': True, |
|
950 | 'success': True, | |
950 | } |
|
951 | } | |
951 | expected = ret |
|
952 | expected = ret | |
952 | self._compare_ok(id_, expected, given=response.body) |
|
953 | self._compare_ok(id_, expected, given=response.body) | |
953 | fixture.destroy_repo(repo_name) |
|
954 | fixture.destroy_repo(repo_name) | |
954 |
|
955 | |||
955 | def test_api_create_repo_by_non_admin_specify_owner(self): |
|
956 | def test_api_create_repo_by_non_admin_specify_owner(self): | |
956 | repo_name = 'api-repo' |
|
957 | repo_name = 'api-repo' | |
957 | owner = 'i-dont-exist' |
|
958 | owner = 'i-dont-exist' | |
958 | id_, params = _build_data(self.apikey_regular, 'create_repo', |
|
959 | id_, params = _build_data(self.apikey_regular, 'create_repo', | |
959 | repo_name=repo_name, |
|
960 | repo_name=repo_name, | |
960 | repo_type=self.REPO_TYPE, |
|
961 | repo_type=self.REPO_TYPE, | |
961 | owner=owner) |
|
962 | owner=owner) | |
962 | response = api_call(self, params) |
|
963 | response = api_call(self, params) | |
963 |
|
964 | |||
964 | expected = 'Only Kallithea admin can specify `owner` param' |
|
965 | expected = 'Only Kallithea admin can specify `owner` param' | |
965 | self._compare_error(id_, expected, given=response.body) |
|
966 | self._compare_error(id_, expected, given=response.body) | |
966 | fixture.destroy_repo(repo_name) |
|
967 | fixture.destroy_repo(repo_name) | |
967 |
|
968 | |||
968 | def test_api_create_repo_exists(self): |
|
969 | def test_api_create_repo_exists(self): | |
969 | repo_name = self.REPO |
|
970 | repo_name = self.REPO | |
970 | id_, params = _build_data(self.apikey, 'create_repo', |
|
971 | id_, params = _build_data(self.apikey, 'create_repo', | |
971 | repo_name=repo_name, |
|
972 | repo_name=repo_name, | |
972 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
973 | owner=base.TEST_USER_ADMIN_LOGIN, | |
973 | repo_type=self.REPO_TYPE,) |
|
974 | repo_type=self.REPO_TYPE,) | |
974 | response = api_call(self, params) |
|
975 | response = api_call(self, params) | |
975 | expected = "repo `%s` already exist" % repo_name |
|
976 | expected = "repo `%s` already exist" % repo_name | |
976 | self._compare_error(id_, expected, given=response.body) |
|
977 | self._compare_error(id_, expected, given=response.body) | |
977 |
|
978 | |||
978 | def test_api_create_repo_dot_dot(self): |
|
979 | def test_api_create_repo_dot_dot(self): | |
979 | # it is only possible to create repositories in existing repo groups - and '..' can't be used |
|
980 | # it is only possible to create repositories in existing repo groups - and '..' can't be used | |
980 | group_name = '%s/..' % TEST_REPO_GROUP |
|
981 | group_name = '%s/..' % TEST_REPO_GROUP | |
981 | repo_name = '%s/%s' % (group_name, 'could-be-outside') |
|
982 | repo_name = '%s/%s' % (group_name, 'could-be-outside') | |
982 | id_, params = _build_data(self.apikey, 'create_repo', |
|
983 | id_, params = _build_data(self.apikey, 'create_repo', | |
983 | repo_name=repo_name, |
|
984 | repo_name=repo_name, | |
984 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
985 | owner=base.TEST_USER_ADMIN_LOGIN, | |
985 | repo_type=self.REPO_TYPE,) |
|
986 | repo_type=self.REPO_TYPE,) | |
986 | response = api_call(self, params) |
|
987 | response = api_call(self, params) | |
987 | expected = 'repo group `%s` not found' % group_name |
|
988 | expected = 'repo group `%s` not found' % group_name | |
988 | self._compare_error(id_, expected, given=response.body) |
|
989 | self._compare_error(id_, expected, given=response.body) | |
989 | fixture.destroy_repo(repo_name) |
|
990 | fixture.destroy_repo(repo_name) | |
990 |
|
991 | |||
991 | @mock.patch.object(RepoModel, 'create', raise_exception) |
|
992 | @mock.patch.object(RepoModel, 'create', raise_exception) | |
992 | def test_api_create_repo_exception_occurred(self): |
|
993 | def test_api_create_repo_exception_occurred(self): | |
993 | repo_name = 'api-repo' |
|
994 | repo_name = 'api-repo' | |
994 | id_, params = _build_data(self.apikey, 'create_repo', |
|
995 | id_, params = _build_data(self.apikey, 'create_repo', | |
995 | repo_name=repo_name, |
|
996 | repo_name=repo_name, | |
996 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
997 | owner=base.TEST_USER_ADMIN_LOGIN, | |
997 | repo_type=self.REPO_TYPE,) |
|
998 | repo_type=self.REPO_TYPE,) | |
998 | response = api_call(self, params) |
|
999 | response = api_call(self, params) | |
999 | expected = 'failed to create repository `%s`' % repo_name |
|
1000 | expected = 'failed to create repository `%s`' % repo_name | |
1000 | self._compare_error(id_, expected, given=response.body) |
|
1001 | self._compare_error(id_, expected, given=response.body) | |
1001 |
|
1002 | |||
1002 | @base.parametrize('changing_attr,updates', [ |
|
1003 | @base.parametrize('changing_attr,updates', [ | |
1003 | ('owner', {'owner': base.TEST_USER_REGULAR_LOGIN}), |
|
1004 | ('owner', {'owner': base.TEST_USER_REGULAR_LOGIN}), | |
1004 | ('description', {'description': 'new description'}), |
|
1005 | ('description', {'description': 'new description'}), | |
1005 | ('clone_uri', {'clone_uri': 'http://example.com/repo'}), # will fail - pulling from non-existing repo should fail |
|
1006 | ('clone_uri', {'clone_uri': 'http://example.com/repo'}), # will fail - pulling from non-existing repo should fail | |
1006 | ('clone_uri', {'clone_uri': '/repo'}), # will fail - pulling from local repo was a mis-feature - it would bypass access control |
|
1007 | ('clone_uri', {'clone_uri': '/repo'}), # will fail - pulling from local repo was a mis-feature - it would bypass access control | |
1007 | ('clone_uri', {'clone_uri': None}), |
|
1008 | ('clone_uri', {'clone_uri': None}), | |
1008 | ('landing_rev', {'landing_rev': 'branch:master'}), |
|
1009 | ('landing_rev', {'landing_rev': 'branch:master'}), | |
1009 | ('enable_statistics', {'enable_statistics': True}), |
|
1010 | ('enable_statistics', {'enable_statistics': True}), | |
1010 | ('enable_downloads', {'enable_downloads': True}), |
|
1011 | ('enable_downloads', {'enable_downloads': True}), | |
1011 | ('name', {'name': 'new_repo_name'}), |
|
1012 | ('name', {'name': 'new_repo_name'}), | |
1012 | ('repo_group', {'group': 'test_group_for_update'}), |
|
1013 | ('repo_group', {'group': 'test_group_for_update'}), | |
1013 | ]) |
|
1014 | ]) | |
1014 | def test_api_update_repo(self, changing_attr, updates): |
|
1015 | def test_api_update_repo(self, changing_attr, updates): | |
1015 | repo_name = 'api_update_me' |
|
1016 | repo_name = 'api_update_me' | |
1016 | repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) |
|
1017 | repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) | |
1017 | if changing_attr == 'repo_group': |
|
1018 | if changing_attr == 'repo_group': | |
1018 | fixture.create_repo_group(updates['group']) |
|
1019 | fixture.create_repo_group(updates['group']) | |
1019 |
|
1020 | |||
1020 | id_, params = _build_data(self.apikey, 'update_repo', |
|
1021 | id_, params = _build_data(self.apikey, 'update_repo', | |
1021 | repoid=repo_name, **updates) |
|
1022 | repoid=repo_name, **updates) | |
1022 | response = api_call(self, params) |
|
1023 | response = api_call(self, params) | |
1023 | if changing_attr == 'name': |
|
1024 | if changing_attr == 'name': | |
1024 | repo_name = updates['name'] |
|
1025 | repo_name = updates['name'] | |
1025 | if changing_attr == 'repo_group': |
|
1026 | if changing_attr == 'repo_group': | |
1026 | repo_name = '/'.join([updates['group'], repo_name]) |
|
1027 | repo_name = '/'.join([updates['group'], repo_name]) | |
1027 | try: |
|
1028 | try: | |
1028 | if changing_attr == 'clone_uri' and updates['clone_uri']: |
|
1029 | if changing_attr == 'clone_uri' and updates['clone_uri']: | |
1029 | expected = 'failed to update repo `%s`' % repo_name |
|
1030 | expected = 'failed to update repo `%s`' % repo_name | |
1030 | self._compare_error(id_, expected, given=response.body) |
|
1031 | self._compare_error(id_, expected, given=response.body) | |
1031 | else: |
|
1032 | else: | |
1032 | expected = { |
|
1033 | expected = { | |
1033 | 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo_name), |
|
1034 | 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo_name), | |
1034 | 'repository': repo.get_api_data() |
|
1035 | 'repository': repo.get_api_data() | |
1035 | } |
|
1036 | } | |
1036 | self._compare_ok(id_, expected, given=response.body) |
|
1037 | self._compare_ok(id_, expected, given=response.body) | |
1037 | finally: |
|
1038 | finally: | |
1038 | fixture.destroy_repo(repo_name) |
|
1039 | fixture.destroy_repo(repo_name) | |
1039 | if changing_attr == 'repo_group': |
|
1040 | if changing_attr == 'repo_group': | |
1040 | fixture.destroy_repo_group(updates['group']) |
|
1041 | fixture.destroy_repo_group(updates['group']) | |
1041 |
|
1042 | |||
1042 | @base.parametrize('changing_attr,updates', [ |
|
1043 | @base.parametrize('changing_attr,updates', [ | |
1043 | ('owner', {'owner': base.TEST_USER_REGULAR_LOGIN}), |
|
1044 | ('owner', {'owner': base.TEST_USER_REGULAR_LOGIN}), | |
1044 | ('description', {'description': 'new description'}), |
|
1045 | ('description', {'description': 'new description'}), | |
1045 | ('clone_uri', {'clone_uri': 'http://example.com/repo'}), # will fail - pulling from non-existing repo should fail |
|
1046 | ('clone_uri', {'clone_uri': 'http://example.com/repo'}), # will fail - pulling from non-existing repo should fail | |
1046 | ('clone_uri', {'clone_uri': '/repo'}), # will fail - pulling from local repo was a mis-feature - it would bypass access control |
|
1047 | ('clone_uri', {'clone_uri': '/repo'}), # will fail - pulling from local repo was a mis-feature - it would bypass access control | |
1047 | ('clone_uri', {'clone_uri': None}), |
|
1048 | ('clone_uri', {'clone_uri': None}), | |
1048 | ('landing_rev', {'landing_rev': 'branch:master'}), |
|
1049 | ('landing_rev', {'landing_rev': 'branch:master'}), | |
1049 | ('enable_statistics', {'enable_statistics': True}), |
|
1050 | ('enable_statistics', {'enable_statistics': True}), | |
1050 | ('enable_downloads', {'enable_downloads': True}), |
|
1051 | ('enable_downloads', {'enable_downloads': True}), | |
1051 | ('name', {'name': 'new_repo_name'}), |
|
1052 | ('name', {'name': 'new_repo_name'}), | |
1052 | ('repo_group', {'group': 'test_group_for_update'}), |
|
1053 | ('repo_group', {'group': 'test_group_for_update'}), | |
1053 | ]) |
|
1054 | ]) | |
1054 | def test_api_update_group_repo(self, changing_attr, updates): |
|
1055 | def test_api_update_group_repo(self, changing_attr, updates): | |
1055 | group_name = 'lololo' |
|
1056 | group_name = 'lololo' | |
1056 | fixture.create_repo_group(group_name) |
|
1057 | fixture.create_repo_group(group_name) | |
1057 | repo_name = '%s/api_update_me' % group_name |
|
1058 | repo_name = '%s/api_update_me' % group_name | |
1058 | repo = fixture.create_repo(repo_name, repo_group=group_name, repo_type=self.REPO_TYPE) |
|
1059 | repo = fixture.create_repo(repo_name, repo_group=group_name, repo_type=self.REPO_TYPE) | |
1059 | if changing_attr == 'repo_group': |
|
1060 | if changing_attr == 'repo_group': | |
1060 | fixture.create_repo_group(updates['group']) |
|
1061 | fixture.create_repo_group(updates['group']) | |
1061 |
|
1062 | |||
1062 | id_, params = _build_data(self.apikey, 'update_repo', |
|
1063 | id_, params = _build_data(self.apikey, 'update_repo', | |
1063 | repoid=repo_name, **updates) |
|
1064 | repoid=repo_name, **updates) | |
1064 | response = api_call(self, params) |
|
1065 | response = api_call(self, params) | |
1065 | if changing_attr == 'name': |
|
1066 | if changing_attr == 'name': | |
1066 | repo_name = '%s/%s' % (group_name, updates['name']) |
|
1067 | repo_name = '%s/%s' % (group_name, updates['name']) | |
1067 | if changing_attr == 'repo_group': |
|
1068 | if changing_attr == 'repo_group': | |
1068 | repo_name = '/'.join([updates['group'], repo_name.rsplit('/', 1)[-1]]) |
|
1069 | repo_name = '/'.join([updates['group'], repo_name.rsplit('/', 1)[-1]]) | |
1069 | try: |
|
1070 | try: | |
1070 | if changing_attr == 'clone_uri' and updates['clone_uri']: |
|
1071 | if changing_attr == 'clone_uri' and updates['clone_uri']: | |
1071 | expected = 'failed to update repo `%s`' % repo_name |
|
1072 | expected = 'failed to update repo `%s`' % repo_name | |
1072 | self._compare_error(id_, expected, given=response.body) |
|
1073 | self._compare_error(id_, expected, given=response.body) | |
1073 | else: |
|
1074 | else: | |
1074 | expected = { |
|
1075 | expected = { | |
1075 | 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo_name), |
|
1076 | 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo_name), | |
1076 | 'repository': repo.get_api_data() |
|
1077 | 'repository': repo.get_api_data() | |
1077 | } |
|
1078 | } | |
1078 | self._compare_ok(id_, expected, given=response.body) |
|
1079 | self._compare_ok(id_, expected, given=response.body) | |
1079 | finally: |
|
1080 | finally: | |
1080 | fixture.destroy_repo(repo_name) |
|
1081 | fixture.destroy_repo(repo_name) | |
1081 | if changing_attr == 'repo_group': |
|
1082 | if changing_attr == 'repo_group': | |
1082 | fixture.destroy_repo_group(updates['group']) |
|
1083 | fixture.destroy_repo_group(updates['group']) | |
1083 | fixture.destroy_repo_group(group_name) |
|
1084 | fixture.destroy_repo_group(group_name) | |
1084 |
|
1085 | |||
1085 | def test_api_update_repo_repo_group_does_not_exist(self): |
|
1086 | def test_api_update_repo_repo_group_does_not_exist(self): | |
1086 | repo_name = 'admin_owned' |
|
1087 | repo_name = 'admin_owned' | |
1087 | fixture.create_repo(repo_name) |
|
1088 | fixture.create_repo(repo_name) | |
1088 | updates = {'group': 'test_group_for_update'} |
|
1089 | updates = {'group': 'test_group_for_update'} | |
1089 | id_, params = _build_data(self.apikey, 'update_repo', |
|
1090 | id_, params = _build_data(self.apikey, 'update_repo', | |
1090 | repoid=repo_name, **updates) |
|
1091 | repoid=repo_name, **updates) | |
1091 | response = api_call(self, params) |
|
1092 | response = api_call(self, params) | |
1092 | try: |
|
1093 | try: | |
1093 | expected = 'repository group `%s` does not exist' % updates['group'] |
|
1094 | expected = 'repository group `%s` does not exist' % updates['group'] | |
1094 | self._compare_error(id_, expected, given=response.body) |
|
1095 | self._compare_error(id_, expected, given=response.body) | |
1095 | finally: |
|
1096 | finally: | |
1096 | fixture.destroy_repo(repo_name) |
|
1097 | fixture.destroy_repo(repo_name) | |
1097 |
|
1098 | |||
1098 | def test_api_update_repo_regular_user_not_allowed(self): |
|
1099 | def test_api_update_repo_regular_user_not_allowed(self): | |
1099 | repo_name = 'admin_owned' |
|
1100 | repo_name = 'admin_owned' | |
1100 | fixture.create_repo(repo_name) |
|
1101 | fixture.create_repo(repo_name) | |
1101 | updates = {'description': 'something else'} |
|
1102 | updates = {'description': 'something else'} | |
1102 | id_, params = _build_data(self.apikey_regular, 'update_repo', |
|
1103 | id_, params = _build_data(self.apikey_regular, 'update_repo', | |
1103 | repoid=repo_name, **updates) |
|
1104 | repoid=repo_name, **updates) | |
1104 | response = api_call(self, params) |
|
1105 | response = api_call(self, params) | |
1105 | try: |
|
1106 | try: | |
1106 | expected = 'repository `%s` does not exist' % repo_name |
|
1107 | expected = 'repository `%s` does not exist' % repo_name | |
1107 | self._compare_error(id_, expected, given=response.body) |
|
1108 | self._compare_error(id_, expected, given=response.body) | |
1108 | finally: |
|
1109 | finally: | |
1109 | fixture.destroy_repo(repo_name) |
|
1110 | fixture.destroy_repo(repo_name) | |
1110 |
|
1111 | |||
1111 | @mock.patch.object(RepoModel, 'update', raise_exception) |
|
1112 | @mock.patch.object(RepoModel, 'update', raise_exception) | |
1112 | def test_api_update_repo_exception_occurred(self): |
|
1113 | def test_api_update_repo_exception_occurred(self): | |
1113 | repo_name = 'api_update_me' |
|
1114 | repo_name = 'api_update_me' | |
1114 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) |
|
1115 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) | |
1115 | id_, params = _build_data(self.apikey, 'update_repo', |
|
1116 | id_, params = _build_data(self.apikey, 'update_repo', | |
1116 | repoid=repo_name, owner=base.TEST_USER_ADMIN_LOGIN,) |
|
1117 | repoid=repo_name, owner=base.TEST_USER_ADMIN_LOGIN,) | |
1117 | response = api_call(self, params) |
|
1118 | response = api_call(self, params) | |
1118 | try: |
|
1119 | try: | |
1119 | expected = 'failed to update repo `%s`' % repo_name |
|
1120 | expected = 'failed to update repo `%s`' % repo_name | |
1120 | self._compare_error(id_, expected, given=response.body) |
|
1121 | self._compare_error(id_, expected, given=response.body) | |
1121 | finally: |
|
1122 | finally: | |
1122 | fixture.destroy_repo(repo_name) |
|
1123 | fixture.destroy_repo(repo_name) | |
1123 |
|
1124 | |||
1124 | def test_api_update_repo_regular_user_change_top_level_repo_name(self): |
|
1125 | def test_api_update_repo_regular_user_change_top_level_repo_name(self): | |
1125 | repo_name = 'admin_owned' |
|
1126 | repo_name = 'admin_owned' | |
1126 | new_repo_name = 'new_repo_name' |
|
1127 | new_repo_name = 'new_repo_name' | |
1127 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) |
|
1128 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) | |
1128 | RepoModel().grant_user_permission(repo=repo_name, |
|
1129 | RepoModel().grant_user_permission(repo=repo_name, | |
1129 | user=self.TEST_USER_LOGIN, |
|
1130 | user=self.TEST_USER_LOGIN, | |
1130 | perm='repository.admin') |
|
1131 | perm='repository.admin') | |
1131 | UserModel().revoke_perm('default', 'hg.create.repository') |
|
1132 | UserModel().revoke_perm('default', 'hg.create.repository') | |
1132 | UserModel().grant_perm('default', 'hg.create.none') |
|
1133 | UserModel().grant_perm('default', 'hg.create.none') | |
1133 | updates = {'name': new_repo_name} |
|
1134 | updates = {'name': new_repo_name} | |
1134 | id_, params = _build_data(self.apikey_regular, 'update_repo', |
|
1135 | id_, params = _build_data(self.apikey_regular, 'update_repo', | |
1135 | repoid=repo_name, **updates) |
|
1136 | repoid=repo_name, **updates) | |
1136 | response = api_call(self, params) |
|
1137 | response = api_call(self, params) | |
1137 | try: |
|
1138 | try: | |
1138 | expected = 'no permission to create (or move) top level repositories' |
|
1139 | expected = 'no permission to create (or move) top level repositories' | |
1139 | self._compare_error(id_, expected, given=response.body) |
|
1140 | self._compare_error(id_, expected, given=response.body) | |
1140 | finally: |
|
1141 | finally: | |
1141 | fixture.destroy_repo(repo_name) |
|
1142 | fixture.destroy_repo(repo_name) | |
1142 | fixture.destroy_repo(new_repo_name) |
|
1143 | fixture.destroy_repo(new_repo_name) | |
1143 |
|
1144 | |||
1144 | def test_api_update_repo_regular_user_change_repo_name_allowed(self): |
|
1145 | def test_api_update_repo_regular_user_change_repo_name_allowed(self): | |
1145 | repo_name = 'admin_owned' |
|
1146 | repo_name = 'admin_owned' | |
1146 | new_repo_name = 'new_repo_name' |
|
1147 | new_repo_name = 'new_repo_name' | |
1147 | repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) |
|
1148 | repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) | |
1148 | RepoModel().grant_user_permission(repo=repo_name, |
|
1149 | RepoModel().grant_user_permission(repo=repo_name, | |
1149 | user=self.TEST_USER_LOGIN, |
|
1150 | user=self.TEST_USER_LOGIN, | |
1150 | perm='repository.admin') |
|
1151 | perm='repository.admin') | |
1151 | UserModel().revoke_perm('default', 'hg.create.none') |
|
1152 | UserModel().revoke_perm('default', 'hg.create.none') | |
1152 | UserModel().grant_perm('default', 'hg.create.repository') |
|
1153 | UserModel().grant_perm('default', 'hg.create.repository') | |
1153 | updates = {'name': new_repo_name} |
|
1154 | updates = {'name': new_repo_name} | |
1154 | id_, params = _build_data(self.apikey_regular, 'update_repo', |
|
1155 | id_, params = _build_data(self.apikey_regular, 'update_repo', | |
1155 | repoid=repo_name, **updates) |
|
1156 | repoid=repo_name, **updates) | |
1156 | response = api_call(self, params) |
|
1157 | response = api_call(self, params) | |
1157 | try: |
|
1158 | try: | |
1158 | expected = { |
|
1159 | expected = { | |
1159 | 'msg': 'updated repo ID:%s %s' % (repo.repo_id, new_repo_name), |
|
1160 | 'msg': 'updated repo ID:%s %s' % (repo.repo_id, new_repo_name), | |
1160 | 'repository': repo.get_api_data() |
|
1161 | 'repository': repo.get_api_data() | |
1161 | } |
|
1162 | } | |
1162 | self._compare_ok(id_, expected, given=response.body) |
|
1163 | self._compare_ok(id_, expected, given=response.body) | |
1163 | finally: |
|
1164 | finally: | |
1164 | fixture.destroy_repo(repo_name) |
|
1165 | fixture.destroy_repo(repo_name) | |
1165 | fixture.destroy_repo(new_repo_name) |
|
1166 | fixture.destroy_repo(new_repo_name) | |
1166 |
|
1167 | |||
1167 | def test_api_update_repo_regular_user_change_owner(self): |
|
1168 | def test_api_update_repo_regular_user_change_owner(self): | |
1168 | repo_name = 'admin_owned' |
|
1169 | repo_name = 'admin_owned' | |
1169 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) |
|
1170 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) | |
1170 | RepoModel().grant_user_permission(repo=repo_name, |
|
1171 | RepoModel().grant_user_permission(repo=repo_name, | |
1171 | user=self.TEST_USER_LOGIN, |
|
1172 | user=self.TEST_USER_LOGIN, | |
1172 | perm='repository.admin') |
|
1173 | perm='repository.admin') | |
1173 | updates = {'owner': base.TEST_USER_ADMIN_LOGIN} |
|
1174 | updates = {'owner': base.TEST_USER_ADMIN_LOGIN} | |
1174 | id_, params = _build_data(self.apikey_regular, 'update_repo', |
|
1175 | id_, params = _build_data(self.apikey_regular, 'update_repo', | |
1175 | repoid=repo_name, **updates) |
|
1176 | repoid=repo_name, **updates) | |
1176 | response = api_call(self, params) |
|
1177 | response = api_call(self, params) | |
1177 | try: |
|
1178 | try: | |
1178 | expected = 'Only Kallithea admin can specify `owner` param' |
|
1179 | expected = 'Only Kallithea admin can specify `owner` param' | |
1179 | self._compare_error(id_, expected, given=response.body) |
|
1180 | self._compare_error(id_, expected, given=response.body) | |
1180 | finally: |
|
1181 | finally: | |
1181 | fixture.destroy_repo(repo_name) |
|
1182 | fixture.destroy_repo(repo_name) | |
1182 |
|
1183 | |||
1183 | def test_api_delete_repo(self): |
|
1184 | def test_api_delete_repo(self): | |
1184 | repo_name = 'api_delete_me' |
|
1185 | repo_name = 'api_delete_me' | |
1185 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) |
|
1186 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) | |
1186 |
|
1187 | |||
1187 | id_, params = _build_data(self.apikey, 'delete_repo', |
|
1188 | id_, params = _build_data(self.apikey, 'delete_repo', | |
1188 | repoid=repo_name, ) |
|
1189 | repoid=repo_name, ) | |
1189 | response = api_call(self, params) |
|
1190 | response = api_call(self, params) | |
1190 |
|
1191 | |||
1191 | ret = { |
|
1192 | ret = { | |
1192 | 'msg': 'Deleted repository `%s`' % repo_name, |
|
1193 | 'msg': 'Deleted repository `%s`' % repo_name, | |
1193 | 'success': True |
|
1194 | 'success': True | |
1194 | } |
|
1195 | } | |
1195 | try: |
|
1196 | try: | |
1196 | expected = ret |
|
1197 | expected = ret | |
1197 | self._compare_ok(id_, expected, given=response.body) |
|
1198 | self._compare_ok(id_, expected, given=response.body) | |
1198 | finally: |
|
1199 | finally: | |
1199 | fixture.destroy_repo(repo_name) |
|
1200 | fixture.destroy_repo(repo_name) | |
1200 |
|
1201 | |||
1201 | def test_api_delete_repo_by_non_admin(self): |
|
1202 | def test_api_delete_repo_by_non_admin(self): | |
1202 | repo_name = 'api_delete_me' |
|
1203 | repo_name = 'api_delete_me' | |
1203 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE, |
|
1204 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE, | |
1204 | cur_user=self.TEST_USER_LOGIN) |
|
1205 | cur_user=self.TEST_USER_LOGIN) | |
1205 | id_, params = _build_data(self.apikey_regular, 'delete_repo', |
|
1206 | id_, params = _build_data(self.apikey_regular, 'delete_repo', | |
1206 | repoid=repo_name, ) |
|
1207 | repoid=repo_name, ) | |
1207 | response = api_call(self, params) |
|
1208 | response = api_call(self, params) | |
1208 |
|
1209 | |||
1209 | ret = { |
|
1210 | ret = { | |
1210 | 'msg': 'Deleted repository `%s`' % repo_name, |
|
1211 | 'msg': 'Deleted repository `%s`' % repo_name, | |
1211 | 'success': True |
|
1212 | 'success': True | |
1212 | } |
|
1213 | } | |
1213 | try: |
|
1214 | try: | |
1214 | expected = ret |
|
1215 | expected = ret | |
1215 | self._compare_ok(id_, expected, given=response.body) |
|
1216 | self._compare_ok(id_, expected, given=response.body) | |
1216 | finally: |
|
1217 | finally: | |
1217 | fixture.destroy_repo(repo_name) |
|
1218 | fixture.destroy_repo(repo_name) | |
1218 |
|
1219 | |||
1219 | def test_api_delete_repo_by_non_admin_no_permission(self): |
|
1220 | def test_api_delete_repo_by_non_admin_no_permission(self): | |
1220 | repo_name = 'api_delete_me' |
|
1221 | repo_name = 'api_delete_me' | |
1221 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) |
|
1222 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) | |
1222 | try: |
|
1223 | try: | |
1223 | id_, params = _build_data(self.apikey_regular, 'delete_repo', |
|
1224 | id_, params = _build_data(self.apikey_regular, 'delete_repo', | |
1224 | repoid=repo_name, ) |
|
1225 | repoid=repo_name, ) | |
1225 | response = api_call(self, params) |
|
1226 | response = api_call(self, params) | |
1226 | expected = 'repository `%s` does not exist' % (repo_name) |
|
1227 | expected = 'repository `%s` does not exist' % (repo_name) | |
1227 | self._compare_error(id_, expected, given=response.body) |
|
1228 | self._compare_error(id_, expected, given=response.body) | |
1228 | finally: |
|
1229 | finally: | |
1229 | fixture.destroy_repo(repo_name) |
|
1230 | fixture.destroy_repo(repo_name) | |
1230 |
|
1231 | |||
1231 | def test_api_delete_repo_exception_occurred(self): |
|
1232 | def test_api_delete_repo_exception_occurred(self): | |
1232 | repo_name = 'api_delete_me' |
|
1233 | repo_name = 'api_delete_me' | |
1233 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) |
|
1234 | fixture.create_repo(repo_name, repo_type=self.REPO_TYPE) | |
1234 | try: |
|
1235 | try: | |
1235 | with mock.patch.object(RepoModel, 'delete', raise_exception): |
|
1236 | with mock.patch.object(RepoModel, 'delete', raise_exception): | |
1236 | id_, params = _build_data(self.apikey, 'delete_repo', |
|
1237 | id_, params = _build_data(self.apikey, 'delete_repo', | |
1237 | repoid=repo_name, ) |
|
1238 | repoid=repo_name, ) | |
1238 | response = api_call(self, params) |
|
1239 | response = api_call(self, params) | |
1239 |
|
1240 | |||
1240 | expected = 'failed to delete repository `%s`' % repo_name |
|
1241 | expected = 'failed to delete repository `%s`' % repo_name | |
1241 | self._compare_error(id_, expected, given=response.body) |
|
1242 | self._compare_error(id_, expected, given=response.body) | |
1242 | finally: |
|
1243 | finally: | |
1243 | fixture.destroy_repo(repo_name) |
|
1244 | fixture.destroy_repo(repo_name) | |
1244 |
|
1245 | |||
1245 | def test_api_fork_repo(self): |
|
1246 | def test_api_fork_repo(self): | |
1246 | fork_name = 'api-repo-fork' |
|
1247 | fork_name = 'api-repo-fork' | |
1247 | id_, params = _build_data(self.apikey, 'fork_repo', |
|
1248 | id_, params = _build_data(self.apikey, 'fork_repo', | |
1248 | repoid=self.REPO, |
|
1249 | repoid=self.REPO, | |
1249 | fork_name=fork_name, |
|
1250 | fork_name=fork_name, | |
1250 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
1251 | owner=base.TEST_USER_ADMIN_LOGIN, | |
1251 | ) |
|
1252 | ) | |
1252 | response = api_call(self, params) |
|
1253 | response = api_call(self, params) | |
1253 |
|
1254 | |||
1254 | ret = { |
|
1255 | ret = { | |
1255 | 'msg': 'Created fork of `%s` as `%s`' % (self.REPO, |
|
1256 | 'msg': 'Created fork of `%s` as `%s`' % (self.REPO, | |
1256 | fork_name), |
|
1257 | fork_name), | |
1257 | 'success': True, |
|
1258 | 'success': True, | |
1258 | } |
|
1259 | } | |
1259 | expected = ret |
|
1260 | expected = ret | |
1260 | self._compare_ok(id_, expected, given=response.body) |
|
1261 | self._compare_ok(id_, expected, given=response.body) | |
1261 | fixture.destroy_repo(fork_name) |
|
1262 | fixture.destroy_repo(fork_name) | |
1262 |
|
1263 | |||
1263 | @base.parametrize('fork_name', [ |
|
1264 | @base.parametrize('fork_name', [ | |
1264 | 'api-repo-fork', |
|
1265 | 'api-repo-fork', | |
1265 | '%s/api-repo-fork' % TEST_REPO_GROUP, |
|
1266 | '%s/api-repo-fork' % TEST_REPO_GROUP, | |
1266 | ]) |
|
1267 | ]) | |
1267 | def test_api_fork_repo_non_admin(self, fork_name): |
|
1268 | def test_api_fork_repo_non_admin(self, fork_name): | |
1268 | RepoGroupModel().grant_user_permission(TEST_REPO_GROUP, |
|
1269 | RepoGroupModel().grant_user_permission(TEST_REPO_GROUP, | |
1269 | self.TEST_USER_LOGIN, |
|
1270 | self.TEST_USER_LOGIN, | |
1270 | 'group.write') |
|
1271 | 'group.write') | |
1271 | id_, params = _build_data(self.apikey_regular, 'fork_repo', |
|
1272 | id_, params = _build_data(self.apikey_regular, 'fork_repo', | |
1272 | repoid=self.REPO, |
|
1273 | repoid=self.REPO, | |
1273 | fork_name=fork_name, |
|
1274 | fork_name=fork_name, | |
1274 | ) |
|
1275 | ) | |
1275 | response = api_call(self, params) |
|
1276 | response = api_call(self, params) | |
1276 |
|
1277 | |||
1277 | ret = { |
|
1278 | ret = { | |
1278 | 'msg': 'Created fork of `%s` as `%s`' % (self.REPO, |
|
1279 | 'msg': 'Created fork of `%s` as `%s`' % (self.REPO, | |
1279 | fork_name), |
|
1280 | fork_name), | |
1280 | 'success': True, |
|
1281 | 'success': True, | |
1281 | } |
|
1282 | } | |
1282 | expected = ret |
|
1283 | expected = ret | |
1283 | self._compare_ok(id_, expected, given=response.body) |
|
1284 | self._compare_ok(id_, expected, given=response.body) | |
1284 | fixture.destroy_repo(fork_name) |
|
1285 | fixture.destroy_repo(fork_name) | |
1285 |
|
1286 | |||
1286 | def test_api_fork_repo_non_admin_specify_owner(self): |
|
1287 | def test_api_fork_repo_non_admin_specify_owner(self): | |
1287 | fork_name = 'api-repo-fork' |
|
1288 | fork_name = 'api-repo-fork' | |
1288 | id_, params = _build_data(self.apikey_regular, 'fork_repo', |
|
1289 | id_, params = _build_data(self.apikey_regular, 'fork_repo', | |
1289 | repoid=self.REPO, |
|
1290 | repoid=self.REPO, | |
1290 | fork_name=fork_name, |
|
1291 | fork_name=fork_name, | |
1291 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
1292 | owner=base.TEST_USER_ADMIN_LOGIN, | |
1292 | ) |
|
1293 | ) | |
1293 | response = api_call(self, params) |
|
1294 | response = api_call(self, params) | |
1294 | expected = 'Only Kallithea admin can specify `owner` param' |
|
1295 | expected = 'Only Kallithea admin can specify `owner` param' | |
1295 | self._compare_error(id_, expected, given=response.body) |
|
1296 | self._compare_error(id_, expected, given=response.body) | |
1296 | fixture.destroy_repo(fork_name) |
|
1297 | fixture.destroy_repo(fork_name) | |
1297 |
|
1298 | |||
1298 | def test_api_fork_repo_non_admin_no_permission_to_fork(self): |
|
1299 | def test_api_fork_repo_non_admin_no_permission_to_fork(self): | |
1299 | RepoModel().grant_user_permission(repo=self.REPO, |
|
1300 | RepoModel().grant_user_permission(repo=self.REPO, | |
1300 | user=db.User.DEFAULT_USER_NAME, |
|
1301 | user=db.User.DEFAULT_USER_NAME, | |
1301 | perm='repository.none') |
|
1302 | perm='repository.none') | |
1302 | fork_name = 'api-repo-fork' |
|
1303 | fork_name = 'api-repo-fork' | |
1303 | try: |
|
1304 | try: | |
1304 | id_, params = _build_data(self.apikey_regular, 'fork_repo', |
|
1305 | id_, params = _build_data(self.apikey_regular, 'fork_repo', | |
1305 | repoid=self.REPO, |
|
1306 | repoid=self.REPO, | |
1306 | fork_name=fork_name, |
|
1307 | fork_name=fork_name, | |
1307 | ) |
|
1308 | ) | |
1308 | response = api_call(self, params) |
|
1309 | response = api_call(self, params) | |
1309 | expected = 'repository `%s` does not exist' % (self.REPO) |
|
1310 | expected = 'repository `%s` does not exist' % (self.REPO) | |
1310 | self._compare_error(id_, expected, given=response.body) |
|
1311 | self._compare_error(id_, expected, given=response.body) | |
1311 | finally: |
|
1312 | finally: | |
1312 | RepoModel().grant_user_permission(repo=self.REPO, |
|
1313 | RepoModel().grant_user_permission(repo=self.REPO, | |
1313 | user=db.User.DEFAULT_USER_NAME, |
|
1314 | user=db.User.DEFAULT_USER_NAME, | |
1314 | perm='repository.read') |
|
1315 | perm='repository.read') | |
1315 | fixture.destroy_repo(fork_name) |
|
1316 | fixture.destroy_repo(fork_name) | |
1316 |
|
1317 | |||
1317 | @base.parametrize('name,perm', [ |
|
1318 | @base.parametrize('name,perm', [ | |
1318 | ('read', 'repository.read'), |
|
1319 | ('read', 'repository.read'), | |
1319 | ('write', 'repository.write'), |
|
1320 | ('write', 'repository.write'), | |
1320 | ('admin', 'repository.admin'), |
|
1321 | ('admin', 'repository.admin'), | |
1321 | ]) |
|
1322 | ]) | |
1322 | def test_api_fork_repo_non_admin_no_create_repo_permission(self, name, perm): |
|
1323 | def test_api_fork_repo_non_admin_no_create_repo_permission(self, name, perm): | |
1323 | fork_name = 'api-repo-fork' |
|
1324 | fork_name = 'api-repo-fork' | |
1324 | # regardless of base repository permission, forking is disallowed |
|
1325 | # regardless of base repository permission, forking is disallowed | |
1325 | # when repository creation is disabled |
|
1326 | # when repository creation is disabled | |
1326 | RepoModel().grant_user_permission(repo=self.REPO, |
|
1327 | RepoModel().grant_user_permission(repo=self.REPO, | |
1327 | user=self.TEST_USER_LOGIN, |
|
1328 | user=self.TEST_USER_LOGIN, | |
1328 | perm=perm) |
|
1329 | perm=perm) | |
1329 | UserModel().revoke_perm('default', 'hg.create.repository') |
|
1330 | UserModel().revoke_perm('default', 'hg.create.repository') | |
1330 | UserModel().grant_perm('default', 'hg.create.none') |
|
1331 | UserModel().grant_perm('default', 'hg.create.none') | |
1331 | id_, params = _build_data(self.apikey_regular, 'fork_repo', |
|
1332 | id_, params = _build_data(self.apikey_regular, 'fork_repo', | |
1332 | repoid=self.REPO, |
|
1333 | repoid=self.REPO, | |
1333 | fork_name=fork_name, |
|
1334 | fork_name=fork_name, | |
1334 | ) |
|
1335 | ) | |
1335 | response = api_call(self, params) |
|
1336 | response = api_call(self, params) | |
1336 | expected = 'no permission to create top level repo' |
|
1337 | expected = 'no permission to create top level repo' | |
1337 | self._compare_error(id_, expected, given=response.body) |
|
1338 | self._compare_error(id_, expected, given=response.body) | |
1338 | fixture.destroy_repo(fork_name) |
|
1339 | fixture.destroy_repo(fork_name) | |
1339 |
|
1340 | |||
1340 | def test_api_fork_repo_unknown_owner(self): |
|
1341 | def test_api_fork_repo_unknown_owner(self): | |
1341 | fork_name = 'api-repo-fork' |
|
1342 | fork_name = 'api-repo-fork' | |
1342 | owner = 'i-dont-exist' |
|
1343 | owner = 'i-dont-exist' | |
1343 | id_, params = _build_data(self.apikey, 'fork_repo', |
|
1344 | id_, params = _build_data(self.apikey, 'fork_repo', | |
1344 | repoid=self.REPO, |
|
1345 | repoid=self.REPO, | |
1345 | fork_name=fork_name, |
|
1346 | fork_name=fork_name, | |
1346 | owner=owner, |
|
1347 | owner=owner, | |
1347 | ) |
|
1348 | ) | |
1348 | response = api_call(self, params) |
|
1349 | response = api_call(self, params) | |
1349 | expected = 'user `%s` does not exist' % owner |
|
1350 | expected = 'user `%s` does not exist' % owner | |
1350 | self._compare_error(id_, expected, given=response.body) |
|
1351 | self._compare_error(id_, expected, given=response.body) | |
1351 |
|
1352 | |||
1352 | def test_api_fork_repo_fork_exists(self): |
|
1353 | def test_api_fork_repo_fork_exists(self): | |
1353 | fork_name = 'api-repo-fork' |
|
1354 | fork_name = 'api-repo-fork' | |
1354 | fixture.create_fork(self.REPO, fork_name) |
|
1355 | fixture.create_fork(self.REPO, fork_name) | |
1355 |
|
1356 | |||
1356 | try: |
|
1357 | try: | |
1357 | fork_name = 'api-repo-fork' |
|
1358 | fork_name = 'api-repo-fork' | |
1358 |
|
1359 | |||
1359 | id_, params = _build_data(self.apikey, 'fork_repo', |
|
1360 | id_, params = _build_data(self.apikey, 'fork_repo', | |
1360 | repoid=self.REPO, |
|
1361 | repoid=self.REPO, | |
1361 | fork_name=fork_name, |
|
1362 | fork_name=fork_name, | |
1362 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
1363 | owner=base.TEST_USER_ADMIN_LOGIN, | |
1363 | ) |
|
1364 | ) | |
1364 | response = api_call(self, params) |
|
1365 | response = api_call(self, params) | |
1365 |
|
1366 | |||
1366 | expected = "fork `%s` already exist" % fork_name |
|
1367 | expected = "fork `%s` already exist" % fork_name | |
1367 | self._compare_error(id_, expected, given=response.body) |
|
1368 | self._compare_error(id_, expected, given=response.body) | |
1368 | finally: |
|
1369 | finally: | |
1369 | fixture.destroy_repo(fork_name) |
|
1370 | fixture.destroy_repo(fork_name) | |
1370 |
|
1371 | |||
1371 | def test_api_fork_repo_repo_exists(self): |
|
1372 | def test_api_fork_repo_repo_exists(self): | |
1372 | fork_name = self.REPO |
|
1373 | fork_name = self.REPO | |
1373 |
|
1374 | |||
1374 | id_, params = _build_data(self.apikey, 'fork_repo', |
|
1375 | id_, params = _build_data(self.apikey, 'fork_repo', | |
1375 | repoid=self.REPO, |
|
1376 | repoid=self.REPO, | |
1376 | fork_name=fork_name, |
|
1377 | fork_name=fork_name, | |
1377 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
1378 | owner=base.TEST_USER_ADMIN_LOGIN, | |
1378 | ) |
|
1379 | ) | |
1379 | response = api_call(self, params) |
|
1380 | response = api_call(self, params) | |
1380 |
|
1381 | |||
1381 | expected = "repo `%s` already exist" % fork_name |
|
1382 | expected = "repo `%s` already exist" % fork_name | |
1382 | self._compare_error(id_, expected, given=response.body) |
|
1383 | self._compare_error(id_, expected, given=response.body) | |
1383 |
|
1384 | |||
1384 | @mock.patch.object(RepoModel, 'create_fork', raise_exception) |
|
1385 | @mock.patch.object(RepoModel, 'create_fork', raise_exception) | |
1385 | def test_api_fork_repo_exception_occurred(self): |
|
1386 | def test_api_fork_repo_exception_occurred(self): | |
1386 | fork_name = 'api-repo-fork' |
|
1387 | fork_name = 'api-repo-fork' | |
1387 | id_, params = _build_data(self.apikey, 'fork_repo', |
|
1388 | id_, params = _build_data(self.apikey, 'fork_repo', | |
1388 | repoid=self.REPO, |
|
1389 | repoid=self.REPO, | |
1389 | fork_name=fork_name, |
|
1390 | fork_name=fork_name, | |
1390 | owner=base.TEST_USER_ADMIN_LOGIN, |
|
1391 | owner=base.TEST_USER_ADMIN_LOGIN, | |
1391 | ) |
|
1392 | ) | |
1392 | response = api_call(self, params) |
|
1393 | response = api_call(self, params) | |
1393 |
|
1394 | |||
1394 | expected = 'failed to fork repository `%s` as `%s`' % (self.REPO, |
|
1395 | expected = 'failed to fork repository `%s` as `%s`' % (self.REPO, | |
1395 | fork_name) |
|
1396 | fork_name) | |
1396 | self._compare_error(id_, expected, given=response.body) |
|
1397 | self._compare_error(id_, expected, given=response.body) | |
1397 |
|
1398 | |||
1398 | def test_api_get_user_group(self): |
|
1399 | def test_api_get_user_group(self): | |
1399 | id_, params = _build_data(self.apikey, 'get_user_group', |
|
1400 | id_, params = _build_data(self.apikey, 'get_user_group', | |
1400 | usergroupid=TEST_USER_GROUP) |
|
1401 | usergroupid=TEST_USER_GROUP) | |
1401 | response = api_call(self, params) |
|
1402 | response = api_call(self, params) | |
1402 |
|
1403 | |||
1403 | user_group = UserGroupModel().get_group(TEST_USER_GROUP) |
|
1404 | user_group = UserGroupModel().get_group(TEST_USER_GROUP) | |
1404 | members = [] |
|
1405 | members = [] | |
1405 | for user in user_group.members: |
|
1406 | for user in user_group.members: | |
1406 | user = user.user |
|
1407 | user = user.user | |
1407 | members.append(user.get_api_data()) |
|
1408 | members.append(user.get_api_data()) | |
1408 |
|
1409 | |||
1409 | ret = user_group.get_api_data() |
|
1410 | ret = user_group.get_api_data() | |
1410 | ret['members'] = members |
|
1411 | ret['members'] = members | |
1411 | expected = ret |
|
1412 | expected = ret | |
1412 | self._compare_ok(id_, expected, given=response.body) |
|
1413 | self._compare_ok(id_, expected, given=response.body) | |
1413 |
|
1414 | |||
1414 | def test_api_get_user_groups(self): |
|
1415 | def test_api_get_user_groups(self): | |
1415 | gr_name = 'test_user_group2' |
|
1416 | gr_name = 'test_user_group2' | |
1416 | make_user_group(gr_name) |
|
1417 | make_user_group(gr_name) | |
1417 |
|
1418 | |||
1418 | try: |
|
1419 | try: | |
1419 | id_, params = _build_data(self.apikey, 'get_user_groups', ) |
|
1420 | id_, params = _build_data(self.apikey, 'get_user_groups', ) | |
1420 | response = api_call(self, params) |
|
1421 | response = api_call(self, params) | |
1421 |
|
1422 | |||
1422 | expected = [] |
|
1423 | expected = [] | |
1423 | for gr_name in [TEST_USER_GROUP, 'test_user_group2']: |
|
1424 | for gr_name in [TEST_USER_GROUP, 'test_user_group2']: | |
1424 | user_group = UserGroupModel().get_group(gr_name) |
|
1425 | user_group = UserGroupModel().get_group(gr_name) | |
1425 | ret = user_group.get_api_data() |
|
1426 | ret = user_group.get_api_data() | |
1426 | expected.append(ret) |
|
1427 | expected.append(ret) | |
1427 | self._compare_ok(id_, expected, given=response.body) |
|
1428 | self._compare_ok(id_, expected, given=response.body) | |
1428 | finally: |
|
1429 | finally: | |
1429 | fixture.destroy_user_group(gr_name) |
|
1430 | fixture.destroy_user_group(gr_name) | |
1430 |
|
1431 | |||
1431 | def test_api_create_user_group(self): |
|
1432 | def test_api_create_user_group(self): | |
1432 | group_name = 'some_new_group' |
|
1433 | group_name = 'some_new_group' | |
1433 | id_, params = _build_data(self.apikey, 'create_user_group', |
|
1434 | id_, params = _build_data(self.apikey, 'create_user_group', | |
1434 | group_name=group_name) |
|
1435 | group_name=group_name) | |
1435 | response = api_call(self, params) |
|
1436 | response = api_call(self, params) | |
1436 |
|
1437 | |||
1437 | ret = { |
|
1438 | ret = { | |
1438 | 'msg': 'created new user group `%s`' % group_name, |
|
1439 | 'msg': 'created new user group `%s`' % group_name, | |
1439 | 'user_group': jsonify(UserGroupModel() \ |
|
1440 | 'user_group': jsonify(UserGroupModel() \ | |
1440 | .get_by_name(group_name) \ |
|
1441 | .get_by_name(group_name) \ | |
1441 | .get_api_data()) |
|
1442 | .get_api_data()) | |
1442 | } |
|
1443 | } | |
1443 | expected = ret |
|
1444 | expected = ret | |
1444 | self._compare_ok(id_, expected, given=response.body) |
|
1445 | self._compare_ok(id_, expected, given=response.body) | |
1445 |
|
1446 | |||
1446 | fixture.destroy_user_group(group_name) |
|
1447 | fixture.destroy_user_group(group_name) | |
1447 |
|
1448 | |||
1448 | def test_api_get_user_group_that_exist(self): |
|
1449 | def test_api_get_user_group_that_exist(self): | |
1449 | id_, params = _build_data(self.apikey, 'create_user_group', |
|
1450 | id_, params = _build_data(self.apikey, 'create_user_group', | |
1450 | group_name=TEST_USER_GROUP) |
|
1451 | group_name=TEST_USER_GROUP) | |
1451 | response = api_call(self, params) |
|
1452 | response = api_call(self, params) | |
1452 |
|
1453 | |||
1453 | expected = "user group `%s` already exist" % TEST_USER_GROUP |
|
1454 | expected = "user group `%s` already exist" % TEST_USER_GROUP | |
1454 | self._compare_error(id_, expected, given=response.body) |
|
1455 | self._compare_error(id_, expected, given=response.body) | |
1455 |
|
1456 | |||
1456 | @mock.patch.object(UserGroupModel, 'create', raise_exception) |
|
1457 | @mock.patch.object(UserGroupModel, 'create', raise_exception) | |
1457 | def test_api_get_user_group_exception_occurred(self): |
|
1458 | def test_api_get_user_group_exception_occurred(self): | |
1458 | group_name = 'exception_happens' |
|
1459 | group_name = 'exception_happens' | |
1459 | id_, params = _build_data(self.apikey, 'create_user_group', |
|
1460 | id_, params = _build_data(self.apikey, 'create_user_group', | |
1460 | group_name=group_name) |
|
1461 | group_name=group_name) | |
1461 | response = api_call(self, params) |
|
1462 | response = api_call(self, params) | |
1462 |
|
1463 | |||
1463 | expected = 'failed to create group `%s`' % group_name |
|
1464 | expected = 'failed to create group `%s`' % group_name | |
1464 | self._compare_error(id_, expected, given=response.body) |
|
1465 | self._compare_error(id_, expected, given=response.body) | |
1465 |
|
1466 | |||
1466 | @base.parametrize('changing_attr,updates', [ |
|
1467 | @base.parametrize('changing_attr,updates', [ | |
1467 | ('group_name', {'group_name': 'new_group_name'}), |
|
1468 | ('group_name', {'group_name': 'new_group_name'}), | |
1468 | ('group_name', {'group_name': 'test_group_for_update'}), |
|
1469 | ('group_name', {'group_name': 'test_group_for_update'}), | |
1469 | ('owner', {'owner': base.TEST_USER_REGULAR_LOGIN}), |
|
1470 | ('owner', {'owner': base.TEST_USER_REGULAR_LOGIN}), | |
1470 | ('active', {'active': False}), |
|
1471 | ('active', {'active': False}), | |
1471 | ('active', {'active': True}), |
|
1472 | ('active', {'active': True}), | |
1472 | ]) |
|
1473 | ]) | |
1473 | def test_api_update_user_group(self, changing_attr, updates): |
|
1474 | def test_api_update_user_group(self, changing_attr, updates): | |
1474 | gr_name = 'test_group_for_update' |
|
1475 | gr_name = 'test_group_for_update' | |
1475 | user_group = fixture.create_user_group(gr_name) |
|
1476 | user_group = fixture.create_user_group(gr_name) | |
1476 | try: |
|
1477 | try: | |
1477 | id_, params = _build_data(self.apikey, 'update_user_group', |
|
1478 | id_, params = _build_data(self.apikey, 'update_user_group', | |
1478 | usergroupid=gr_name, **updates) |
|
1479 | usergroupid=gr_name, **updates) | |
1479 | response = api_call(self, params) |
|
1480 | response = api_call(self, params) | |
1480 | expected = { |
|
1481 | expected = { | |
1481 | 'msg': 'updated user group ID:%s %s' % (user_group.users_group_id, |
|
1482 | 'msg': 'updated user group ID:%s %s' % (user_group.users_group_id, | |
1482 | user_group.users_group_name), |
|
1483 | user_group.users_group_name), | |
1483 | 'user_group': user_group.get_api_data() |
|
1484 | 'user_group': user_group.get_api_data() | |
1484 | } |
|
1485 | } | |
1485 | self._compare_ok(id_, expected, given=response.body) |
|
1486 | self._compare_ok(id_, expected, given=response.body) | |
1486 | finally: |
|
1487 | finally: | |
1487 | if changing_attr == 'group_name': |
|
1488 | if changing_attr == 'group_name': | |
1488 | # switch to updated name for proper cleanup |
|
1489 | # switch to updated name for proper cleanup | |
1489 | gr_name = updates['group_name'] |
|
1490 | gr_name = updates['group_name'] | |
1490 | fixture.destroy_user_group(gr_name) |
|
1491 | fixture.destroy_user_group(gr_name) | |
1491 |
|
1492 | |||
1492 | @mock.patch.object(UserGroupModel, 'update', raise_exception) |
|
1493 | @mock.patch.object(UserGroupModel, 'update', raise_exception) | |
1493 | def test_api_update_user_group_exception_occurred(self): |
|
1494 | def test_api_update_user_group_exception_occurred(self): | |
1494 | gr_name = 'test_group' |
|
1495 | gr_name = 'test_group' | |
1495 | fixture.create_user_group(gr_name) |
|
1496 | fixture.create_user_group(gr_name) | |
1496 | try: |
|
1497 | try: | |
1497 | id_, params = _build_data(self.apikey, 'update_user_group', |
|
1498 | id_, params = _build_data(self.apikey, 'update_user_group', | |
1498 | usergroupid=gr_name) |
|
1499 | usergroupid=gr_name) | |
1499 | response = api_call(self, params) |
|
1500 | response = api_call(self, params) | |
1500 | expected = 'failed to update user group `%s`' % gr_name |
|
1501 | expected = 'failed to update user group `%s`' % gr_name | |
1501 | self._compare_error(id_, expected, given=response.body) |
|
1502 | self._compare_error(id_, expected, given=response.body) | |
1502 | finally: |
|
1503 | finally: | |
1503 | fixture.destroy_user_group(gr_name) |
|
1504 | fixture.destroy_user_group(gr_name) | |
1504 |
|
1505 | |||
1505 | def test_api_add_user_to_user_group(self): |
|
1506 | def test_api_add_user_to_user_group(self): | |
1506 | gr_name = 'test_group' |
|
1507 | gr_name = 'test_group' | |
1507 | fixture.create_user_group(gr_name) |
|
1508 | fixture.create_user_group(gr_name) | |
1508 | try: |
|
1509 | try: | |
1509 | id_, params = _build_data(self.apikey, 'add_user_to_user_group', |
|
1510 | id_, params = _build_data(self.apikey, 'add_user_to_user_group', | |
1510 | usergroupid=gr_name, |
|
1511 | usergroupid=gr_name, | |
1511 | userid=base.TEST_USER_ADMIN_LOGIN) |
|
1512 | userid=base.TEST_USER_ADMIN_LOGIN) | |
1512 | response = api_call(self, params) |
|
1513 | response = api_call(self, params) | |
1513 | expected = { |
|
1514 | expected = { | |
1514 | 'msg': 'added member `%s` to user group `%s`' % ( |
|
1515 | 'msg': 'added member `%s` to user group `%s`' % ( | |
1515 | base.TEST_USER_ADMIN_LOGIN, gr_name), |
|
1516 | base.TEST_USER_ADMIN_LOGIN, gr_name), | |
1516 | 'success': True |
|
1517 | 'success': True | |
1517 | } |
|
1518 | } | |
1518 | self._compare_ok(id_, expected, given=response.body) |
|
1519 | self._compare_ok(id_, expected, given=response.body) | |
1519 | finally: |
|
1520 | finally: | |
1520 | fixture.destroy_user_group(gr_name) |
|
1521 | fixture.destroy_user_group(gr_name) | |
1521 |
|
1522 | |||
1522 | def test_api_add_user_to_user_group_that_doesnt_exist(self): |
|
1523 | def test_api_add_user_to_user_group_that_doesnt_exist(self): | |
1523 | id_, params = _build_data(self.apikey, 'add_user_to_user_group', |
|
1524 | id_, params = _build_data(self.apikey, 'add_user_to_user_group', | |
1524 | usergroupid='false-group', |
|
1525 | usergroupid='false-group', | |
1525 | userid=base.TEST_USER_ADMIN_LOGIN) |
|
1526 | userid=base.TEST_USER_ADMIN_LOGIN) | |
1526 | response = api_call(self, params) |
|
1527 | response = api_call(self, params) | |
1527 |
|
1528 | |||
1528 | expected = 'user group `%s` does not exist' % 'false-group' |
|
1529 | expected = 'user group `%s` does not exist' % 'false-group' | |
1529 | self._compare_error(id_, expected, given=response.body) |
|
1530 | self._compare_error(id_, expected, given=response.body) | |
1530 |
|
1531 | |||
1531 | @mock.patch.object(UserGroupModel, 'add_user_to_group', raise_exception) |
|
1532 | @mock.patch.object(UserGroupModel, 'add_user_to_group', raise_exception) | |
1532 | def test_api_add_user_to_user_group_exception_occurred(self): |
|
1533 | def test_api_add_user_to_user_group_exception_occurred(self): | |
1533 | gr_name = 'test_group' |
|
1534 | gr_name = 'test_group' | |
1534 | fixture.create_user_group(gr_name) |
|
1535 | fixture.create_user_group(gr_name) | |
1535 | try: |
|
1536 | try: | |
1536 | id_, params = _build_data(self.apikey, 'add_user_to_user_group', |
|
1537 | id_, params = _build_data(self.apikey, 'add_user_to_user_group', | |
1537 | usergroupid=gr_name, |
|
1538 | usergroupid=gr_name, | |
1538 | userid=base.TEST_USER_ADMIN_LOGIN) |
|
1539 | userid=base.TEST_USER_ADMIN_LOGIN) | |
1539 | response = api_call(self, params) |
|
1540 | response = api_call(self, params) | |
1540 | expected = 'failed to add member to user group `%s`' % gr_name |
|
1541 | expected = 'failed to add member to user group `%s`' % gr_name | |
1541 | self._compare_error(id_, expected, given=response.body) |
|
1542 | self._compare_error(id_, expected, given=response.body) | |
1542 | finally: |
|
1543 | finally: | |
1543 | fixture.destroy_user_group(gr_name) |
|
1544 | fixture.destroy_user_group(gr_name) | |
1544 |
|
1545 | |||
1545 | def test_api_remove_user_from_user_group(self): |
|
1546 | def test_api_remove_user_from_user_group(self): | |
1546 | gr_name = 'test_group_3' |
|
1547 | gr_name = 'test_group_3' | |
1547 | gr = fixture.create_user_group(gr_name) |
|
1548 | gr = fixture.create_user_group(gr_name) | |
1548 | UserGroupModel().add_user_to_group(gr, user=base.TEST_USER_ADMIN_LOGIN) |
|
1549 | UserGroupModel().add_user_to_group(gr, user=base.TEST_USER_ADMIN_LOGIN) | |
1549 | meta.Session().commit() |
|
1550 | meta.Session().commit() | |
1550 | try: |
|
1551 | try: | |
1551 | id_, params = _build_data(self.apikey, 'remove_user_from_user_group', |
|
1552 | id_, params = _build_data(self.apikey, 'remove_user_from_user_group', | |
1552 | usergroupid=gr_name, |
|
1553 | usergroupid=gr_name, | |
1553 | userid=base.TEST_USER_ADMIN_LOGIN) |
|
1554 | userid=base.TEST_USER_ADMIN_LOGIN) | |
1554 | response = api_call(self, params) |
|
1555 | response = api_call(self, params) | |
1555 | expected = { |
|
1556 | expected = { | |
1556 | 'msg': 'removed member `%s` from user group `%s`' % ( |
|
1557 | 'msg': 'removed member `%s` from user group `%s`' % ( | |
1557 | base.TEST_USER_ADMIN_LOGIN, gr_name |
|
1558 | base.TEST_USER_ADMIN_LOGIN, gr_name | |
1558 | ), |
|
1559 | ), | |
1559 | 'success': True} |
|
1560 | 'success': True} | |
1560 | self._compare_ok(id_, expected, given=response.body) |
|
1561 | self._compare_ok(id_, expected, given=response.body) | |
1561 | finally: |
|
1562 | finally: | |
1562 | fixture.destroy_user_group(gr_name) |
|
1563 | fixture.destroy_user_group(gr_name) | |
1563 |
|
1564 | |||
1564 | @mock.patch.object(UserGroupModel, 'remove_user_from_group', raise_exception) |
|
1565 | @mock.patch.object(UserGroupModel, 'remove_user_from_group', raise_exception) | |
1565 | def test_api_remove_user_from_user_group_exception_occurred(self): |
|
1566 | def test_api_remove_user_from_user_group_exception_occurred(self): | |
1566 | gr_name = 'test_group_3' |
|
1567 | gr_name = 'test_group_3' | |
1567 | gr = fixture.create_user_group(gr_name) |
|
1568 | gr = fixture.create_user_group(gr_name) | |
1568 | UserGroupModel().add_user_to_group(gr, user=base.TEST_USER_ADMIN_LOGIN) |
|
1569 | UserGroupModel().add_user_to_group(gr, user=base.TEST_USER_ADMIN_LOGIN) | |
1569 | meta.Session().commit() |
|
1570 | meta.Session().commit() | |
1570 | try: |
|
1571 | try: | |
1571 | id_, params = _build_data(self.apikey, 'remove_user_from_user_group', |
|
1572 | id_, params = _build_data(self.apikey, 'remove_user_from_user_group', | |
1572 | usergroupid=gr_name, |
|
1573 | usergroupid=gr_name, | |
1573 | userid=base.TEST_USER_ADMIN_LOGIN) |
|
1574 | userid=base.TEST_USER_ADMIN_LOGIN) | |
1574 | response = api_call(self, params) |
|
1575 | response = api_call(self, params) | |
1575 | expected = 'failed to remove member from user group `%s`' % gr_name |
|
1576 | expected = 'failed to remove member from user group `%s`' % gr_name | |
1576 | self._compare_error(id_, expected, given=response.body) |
|
1577 | self._compare_error(id_, expected, given=response.body) | |
1577 | finally: |
|
1578 | finally: | |
1578 | fixture.destroy_user_group(gr_name) |
|
1579 | fixture.destroy_user_group(gr_name) | |
1579 |
|
1580 | |||
1580 | def test_api_delete_user_group(self): |
|
1581 | def test_api_delete_user_group(self): | |
1581 | gr_name = 'test_group' |
|
1582 | gr_name = 'test_group' | |
1582 | ugroup = fixture.create_user_group(gr_name) |
|
1583 | ugroup = fixture.create_user_group(gr_name) | |
1583 | gr_id = ugroup.users_group_id |
|
1584 | gr_id = ugroup.users_group_id | |
1584 | try: |
|
1585 | try: | |
1585 | id_, params = _build_data(self.apikey, 'delete_user_group', |
|
1586 | id_, params = _build_data(self.apikey, 'delete_user_group', | |
1586 | usergroupid=gr_name) |
|
1587 | usergroupid=gr_name) | |
1587 | response = api_call(self, params) |
|
1588 | response = api_call(self, params) | |
1588 | expected = { |
|
1589 | expected = { | |
1589 | 'user_group': None, |
|
1590 | 'user_group': None, | |
1590 | 'msg': 'deleted user group ID:%s %s' % (gr_id, gr_name) |
|
1591 | 'msg': 'deleted user group ID:%s %s' % (gr_id, gr_name) | |
1591 | } |
|
1592 | } | |
1592 | self._compare_ok(id_, expected, given=response.body) |
|
1593 | self._compare_ok(id_, expected, given=response.body) | |
1593 | finally: |
|
1594 | finally: | |
1594 | if UserGroupModel().get_by_name(gr_name): |
|
1595 | if UserGroupModel().get_by_name(gr_name): | |
1595 | fixture.destroy_user_group(gr_name) |
|
1596 | fixture.destroy_user_group(gr_name) | |
1596 |
|
1597 | |||
1597 | def test_api_delete_user_group_that_is_assigned(self): |
|
1598 | def test_api_delete_user_group_that_is_assigned(self): | |
1598 | gr_name = 'test_group' |
|
1599 | gr_name = 'test_group' | |
1599 | ugroup = fixture.create_user_group(gr_name) |
|
1600 | ugroup = fixture.create_user_group(gr_name) | |
1600 | gr_id = ugroup.users_group_id |
|
1601 | gr_id = ugroup.users_group_id | |
1601 |
|
1602 | |||
1602 | ugr_to_perm = RepoModel().grant_user_group_permission(self.REPO, gr_name, 'repository.write') |
|
1603 | ugr_to_perm = RepoModel().grant_user_group_permission(self.REPO, gr_name, 'repository.write') | |
1603 | msg = 'User Group assigned to %s' % ugr_to_perm.repository.repo_name |
|
1604 | msg = 'User Group assigned to %s' % ugr_to_perm.repository.repo_name | |
1604 |
|
1605 | |||
1605 | try: |
|
1606 | try: | |
1606 | id_, params = _build_data(self.apikey, 'delete_user_group', |
|
1607 | id_, params = _build_data(self.apikey, 'delete_user_group', | |
1607 | usergroupid=gr_name) |
|
1608 | usergroupid=gr_name) | |
1608 | response = api_call(self, params) |
|
1609 | response = api_call(self, params) | |
1609 | expected = msg |
|
1610 | expected = msg | |
1610 | self._compare_error(id_, expected, given=response.body) |
|
1611 | self._compare_error(id_, expected, given=response.body) | |
1611 | finally: |
|
1612 | finally: | |
1612 | if UserGroupModel().get_by_name(gr_name): |
|
1613 | if UserGroupModel().get_by_name(gr_name): | |
1613 | fixture.destroy_user_group(gr_name) |
|
1614 | fixture.destroy_user_group(gr_name) | |
1614 |
|
1615 | |||
1615 | def test_api_delete_user_group_exception_occurred(self): |
|
1616 | def test_api_delete_user_group_exception_occurred(self): | |
1616 | gr_name = 'test_group' |
|
1617 | gr_name = 'test_group' | |
1617 | ugroup = fixture.create_user_group(gr_name) |
|
1618 | ugroup = fixture.create_user_group(gr_name) | |
1618 | gr_id = ugroup.users_group_id |
|
1619 | gr_id = ugroup.users_group_id | |
1619 | id_, params = _build_data(self.apikey, 'delete_user_group', |
|
1620 | id_, params = _build_data(self.apikey, 'delete_user_group', | |
1620 | usergroupid=gr_name) |
|
1621 | usergroupid=gr_name) | |
1621 |
|
1622 | |||
1622 | try: |
|
1623 | try: | |
1623 | with mock.patch.object(UserGroupModel, 'delete', raise_exception): |
|
1624 | with mock.patch.object(UserGroupModel, 'delete', raise_exception): | |
1624 | response = api_call(self, params) |
|
1625 | response = api_call(self, params) | |
1625 | expected = 'failed to delete user group ID:%s %s' % (gr_id, gr_name) |
|
1626 | expected = 'failed to delete user group ID:%s %s' % (gr_id, gr_name) | |
1626 | self._compare_error(id_, expected, given=response.body) |
|
1627 | self._compare_error(id_, expected, given=response.body) | |
1627 | finally: |
|
1628 | finally: | |
1628 | fixture.destroy_user_group(gr_name) |
|
1629 | fixture.destroy_user_group(gr_name) | |
1629 |
|
1630 | |||
1630 | @base.parametrize('name,perm', [ |
|
1631 | @base.parametrize('name,perm', [ | |
1631 | ('none', 'repository.none'), |
|
1632 | ('none', 'repository.none'), | |
1632 | ('read', 'repository.read'), |
|
1633 | ('read', 'repository.read'), | |
1633 | ('write', 'repository.write'), |
|
1634 | ('write', 'repository.write'), | |
1634 | ('admin', 'repository.admin'), |
|
1635 | ('admin', 'repository.admin'), | |
1635 | ]) |
|
1636 | ]) | |
1636 | def test_api_grant_user_permission(self, name, perm): |
|
1637 | def test_api_grant_user_permission(self, name, perm): | |
1637 | id_, params = _build_data(self.apikey, |
|
1638 | id_, params = _build_data(self.apikey, | |
1638 | 'grant_user_permission', |
|
1639 | 'grant_user_permission', | |
1639 | repoid=self.REPO, |
|
1640 | repoid=self.REPO, | |
1640 | userid=base.TEST_USER_ADMIN_LOGIN, |
|
1641 | userid=base.TEST_USER_ADMIN_LOGIN, | |
1641 | perm=perm) |
|
1642 | perm=perm) | |
1642 | response = api_call(self, params) |
|
1643 | response = api_call(self, params) | |
1643 |
|
1644 | |||
1644 | ret = { |
|
1645 | ret = { | |
1645 | 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % ( |
|
1646 | 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % ( | |
1646 | perm, base.TEST_USER_ADMIN_LOGIN, self.REPO |
|
1647 | perm, base.TEST_USER_ADMIN_LOGIN, self.REPO | |
1647 | ), |
|
1648 | ), | |
1648 | 'success': True |
|
1649 | 'success': True | |
1649 | } |
|
1650 | } | |
1650 | expected = ret |
|
1651 | expected = ret | |
1651 | self._compare_ok(id_, expected, given=response.body) |
|
1652 | self._compare_ok(id_, expected, given=response.body) | |
1652 |
|
1653 | |||
1653 | def test_api_grant_user_permission_wrong_permission(self): |
|
1654 | def test_api_grant_user_permission_wrong_permission(self): | |
1654 | perm = 'haha.no.permission' |
|
1655 | perm = 'haha.no.permission' | |
1655 | id_, params = _build_data(self.apikey, |
|
1656 | id_, params = _build_data(self.apikey, | |
1656 | 'grant_user_permission', |
|
1657 | 'grant_user_permission', | |
1657 | repoid=self.REPO, |
|
1658 | repoid=self.REPO, | |
1658 | userid=base.TEST_USER_ADMIN_LOGIN, |
|
1659 | userid=base.TEST_USER_ADMIN_LOGIN, | |
1659 | perm=perm) |
|
1660 | perm=perm) | |
1660 | response = api_call(self, params) |
|
1661 | response = api_call(self, params) | |
1661 |
|
1662 | |||
1662 | expected = 'permission `%s` does not exist' % perm |
|
1663 | expected = 'permission `%s` does not exist' % perm | |
1663 | self._compare_error(id_, expected, given=response.body) |
|
1664 | self._compare_error(id_, expected, given=response.body) | |
1664 |
|
1665 | |||
1665 | @mock.patch.object(RepoModel, 'grant_user_permission', raise_exception) |
|
1666 | @mock.patch.object(RepoModel, 'grant_user_permission', raise_exception) | |
1666 | def test_api_grant_user_permission_exception_when_adding(self): |
|
1667 | def test_api_grant_user_permission_exception_when_adding(self): | |
1667 | perm = 'repository.read' |
|
1668 | perm = 'repository.read' | |
1668 | id_, params = _build_data(self.apikey, |
|
1669 | id_, params = _build_data(self.apikey, | |
1669 | 'grant_user_permission', |
|
1670 | 'grant_user_permission', | |
1670 | repoid=self.REPO, |
|
1671 | repoid=self.REPO, | |
1671 | userid=base.TEST_USER_ADMIN_LOGIN, |
|
1672 | userid=base.TEST_USER_ADMIN_LOGIN, | |
1672 | perm=perm) |
|
1673 | perm=perm) | |
1673 | response = api_call(self, params) |
|
1674 | response = api_call(self, params) | |
1674 |
|
1675 | |||
1675 | expected = 'failed to edit permission for user: `%s` in repo: `%s`' % ( |
|
1676 | expected = 'failed to edit permission for user: `%s` in repo: `%s`' % ( | |
1676 | base.TEST_USER_ADMIN_LOGIN, self.REPO |
|
1677 | base.TEST_USER_ADMIN_LOGIN, self.REPO | |
1677 | ) |
|
1678 | ) | |
1678 | self._compare_error(id_, expected, given=response.body) |
|
1679 | self._compare_error(id_, expected, given=response.body) | |
1679 |
|
1680 | |||
1680 | def test_api_revoke_user_permission(self): |
|
1681 | def test_api_revoke_user_permission(self): | |
1681 | id_, params = _build_data(self.apikey, |
|
1682 | id_, params = _build_data(self.apikey, | |
1682 | 'revoke_user_permission', |
|
1683 | 'revoke_user_permission', | |
1683 | repoid=self.REPO, |
|
1684 | repoid=self.REPO, | |
1684 | userid=base.TEST_USER_ADMIN_LOGIN, ) |
|
1685 | userid=base.TEST_USER_ADMIN_LOGIN, ) | |
1685 | response = api_call(self, params) |
|
1686 | response = api_call(self, params) | |
1686 |
|
1687 | |||
1687 | expected = { |
|
1688 | expected = { | |
1688 | 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % ( |
|
1689 | 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % ( | |
1689 | base.TEST_USER_ADMIN_LOGIN, self.REPO |
|
1690 | base.TEST_USER_ADMIN_LOGIN, self.REPO | |
1690 | ), |
|
1691 | ), | |
1691 | 'success': True |
|
1692 | 'success': True | |
1692 | } |
|
1693 | } | |
1693 | self._compare_ok(id_, expected, given=response.body) |
|
1694 | self._compare_ok(id_, expected, given=response.body) | |
1694 |
|
1695 | |||
1695 | @mock.patch.object(RepoModel, 'revoke_user_permission', raise_exception) |
|
1696 | @mock.patch.object(RepoModel, 'revoke_user_permission', raise_exception) | |
1696 | def test_api_revoke_user_permission_exception_when_adding(self): |
|
1697 | def test_api_revoke_user_permission_exception_when_adding(self): | |
1697 | id_, params = _build_data(self.apikey, |
|
1698 | id_, params = _build_data(self.apikey, | |
1698 | 'revoke_user_permission', |
|
1699 | 'revoke_user_permission', | |
1699 | repoid=self.REPO, |
|
1700 | repoid=self.REPO, | |
1700 | userid=base.TEST_USER_ADMIN_LOGIN, ) |
|
1701 | userid=base.TEST_USER_ADMIN_LOGIN, ) | |
1701 | response = api_call(self, params) |
|
1702 | response = api_call(self, params) | |
1702 |
|
1703 | |||
1703 | expected = 'failed to edit permission for user: `%s` in repo: `%s`' % ( |
|
1704 | expected = 'failed to edit permission for user: `%s` in repo: `%s`' % ( | |
1704 | base.TEST_USER_ADMIN_LOGIN, self.REPO |
|
1705 | base.TEST_USER_ADMIN_LOGIN, self.REPO | |
1705 | ) |
|
1706 | ) | |
1706 | self._compare_error(id_, expected, given=response.body) |
|
1707 | self._compare_error(id_, expected, given=response.body) | |
1707 |
|
1708 | |||
1708 | @base.parametrize('name,perm', [ |
|
1709 | @base.parametrize('name,perm', [ | |
1709 | ('none', 'repository.none'), |
|
1710 | ('none', 'repository.none'), | |
1710 | ('read', 'repository.read'), |
|
1711 | ('read', 'repository.read'), | |
1711 | ('write', 'repository.write'), |
|
1712 | ('write', 'repository.write'), | |
1712 | ('admin', 'repository.admin'), |
|
1713 | ('admin', 'repository.admin'), | |
1713 | ]) |
|
1714 | ]) | |
1714 | def test_api_grant_user_group_permission(self, name, perm): |
|
1715 | def test_api_grant_user_group_permission(self, name, perm): | |
1715 | id_, params = _build_data(self.apikey, |
|
1716 | id_, params = _build_data(self.apikey, | |
1716 | 'grant_user_group_permission', |
|
1717 | 'grant_user_group_permission', | |
1717 | repoid=self.REPO, |
|
1718 | repoid=self.REPO, | |
1718 | usergroupid=TEST_USER_GROUP, |
|
1719 | usergroupid=TEST_USER_GROUP, | |
1719 | perm=perm) |
|
1720 | perm=perm) | |
1720 | response = api_call(self, params) |
|
1721 | response = api_call(self, params) | |
1721 |
|
1722 | |||
1722 | ret = { |
|
1723 | ret = { | |
1723 | 'msg': 'Granted perm: `%s` for user group: `%s` in repo: `%s`' % ( |
|
1724 | 'msg': 'Granted perm: `%s` for user group: `%s` in repo: `%s`' % ( | |
1724 | perm, TEST_USER_GROUP, self.REPO |
|
1725 | perm, TEST_USER_GROUP, self.REPO | |
1725 | ), |
|
1726 | ), | |
1726 | 'success': True |
|
1727 | 'success': True | |
1727 | } |
|
1728 | } | |
1728 | expected = ret |
|
1729 | expected = ret | |
1729 | self._compare_ok(id_, expected, given=response.body) |
|
1730 | self._compare_ok(id_, expected, given=response.body) | |
1730 |
|
1731 | |||
1731 | def test_api_grant_user_group_permission_wrong_permission(self): |
|
1732 | def test_api_grant_user_group_permission_wrong_permission(self): | |
1732 | perm = 'haha.no.permission' |
|
1733 | perm = 'haha.no.permission' | |
1733 | id_, params = _build_data(self.apikey, |
|
1734 | id_, params = _build_data(self.apikey, | |
1734 | 'grant_user_group_permission', |
|
1735 | 'grant_user_group_permission', | |
1735 | repoid=self.REPO, |
|
1736 | repoid=self.REPO, | |
1736 | usergroupid=TEST_USER_GROUP, |
|
1737 | usergroupid=TEST_USER_GROUP, | |
1737 | perm=perm) |
|
1738 | perm=perm) | |
1738 | response = api_call(self, params) |
|
1739 | response = api_call(self, params) | |
1739 |
|
1740 | |||
1740 | expected = 'permission `%s` does not exist' % perm |
|
1741 | expected = 'permission `%s` does not exist' % perm | |
1741 | self._compare_error(id_, expected, given=response.body) |
|
1742 | self._compare_error(id_, expected, given=response.body) | |
1742 |
|
1743 | |||
1743 | @mock.patch.object(RepoModel, 'grant_user_group_permission', raise_exception) |
|
1744 | @mock.patch.object(RepoModel, 'grant_user_group_permission', raise_exception) | |
1744 | def test_api_grant_user_group_permission_exception_when_adding(self): |
|
1745 | def test_api_grant_user_group_permission_exception_when_adding(self): | |
1745 | perm = 'repository.read' |
|
1746 | perm = 'repository.read' | |
1746 | id_, params = _build_data(self.apikey, |
|
1747 | id_, params = _build_data(self.apikey, | |
1747 | 'grant_user_group_permission', |
|
1748 | 'grant_user_group_permission', | |
1748 | repoid=self.REPO, |
|
1749 | repoid=self.REPO, | |
1749 | usergroupid=TEST_USER_GROUP, |
|
1750 | usergroupid=TEST_USER_GROUP, | |
1750 | perm=perm) |
|
1751 | perm=perm) | |
1751 | response = api_call(self, params) |
|
1752 | response = api_call(self, params) | |
1752 |
|
1753 | |||
1753 | expected = 'failed to edit permission for user group: `%s` in repo: `%s`' % ( |
|
1754 | expected = 'failed to edit permission for user group: `%s` in repo: `%s`' % ( | |
1754 | TEST_USER_GROUP, self.REPO |
|
1755 | TEST_USER_GROUP, self.REPO | |
1755 | ) |
|
1756 | ) | |
1756 | self._compare_error(id_, expected, given=response.body) |
|
1757 | self._compare_error(id_, expected, given=response.body) | |
1757 |
|
1758 | |||
1758 | def test_api_revoke_user_group_permission(self): |
|
1759 | def test_api_revoke_user_group_permission(self): | |
1759 | RepoModel().grant_user_group_permission(repo=self.REPO, |
|
1760 | RepoModel().grant_user_group_permission(repo=self.REPO, | |
1760 | group_name=TEST_USER_GROUP, |
|
1761 | group_name=TEST_USER_GROUP, | |
1761 | perm='repository.read') |
|
1762 | perm='repository.read') | |
1762 | meta.Session().commit() |
|
1763 | meta.Session().commit() | |
1763 | id_, params = _build_data(self.apikey, |
|
1764 | id_, params = _build_data(self.apikey, | |
1764 | 'revoke_user_group_permission', |
|
1765 | 'revoke_user_group_permission', | |
1765 | repoid=self.REPO, |
|
1766 | repoid=self.REPO, | |
1766 | usergroupid=TEST_USER_GROUP, ) |
|
1767 | usergroupid=TEST_USER_GROUP, ) | |
1767 | response = api_call(self, params) |
|
1768 | response = api_call(self, params) | |
1768 |
|
1769 | |||
1769 | expected = { |
|
1770 | expected = { | |
1770 | 'msg': 'Revoked perm for user group: `%s` in repo: `%s`' % ( |
|
1771 | 'msg': 'Revoked perm for user group: `%s` in repo: `%s`' % ( | |
1771 | TEST_USER_GROUP, self.REPO |
|
1772 | TEST_USER_GROUP, self.REPO | |
1772 | ), |
|
1773 | ), | |
1773 | 'success': True |
|
1774 | 'success': True | |
1774 | } |
|
1775 | } | |
1775 | self._compare_ok(id_, expected, given=response.body) |
|
1776 | self._compare_ok(id_, expected, given=response.body) | |
1776 |
|
1777 | |||
1777 | @mock.patch.object(RepoModel, 'revoke_user_group_permission', raise_exception) |
|
1778 | @mock.patch.object(RepoModel, 'revoke_user_group_permission', raise_exception) | |
1778 | def test_api_revoke_user_group_permission_exception_when_adding(self): |
|
1779 | def test_api_revoke_user_group_permission_exception_when_adding(self): | |
1779 | id_, params = _build_data(self.apikey, |
|
1780 | id_, params = _build_data(self.apikey, | |
1780 | 'revoke_user_group_permission', |
|
1781 | 'revoke_user_group_permission', | |
1781 | repoid=self.REPO, |
|
1782 | repoid=self.REPO, | |
1782 | usergroupid=TEST_USER_GROUP, ) |
|
1783 | usergroupid=TEST_USER_GROUP, ) | |
1783 | response = api_call(self, params) |
|
1784 | response = api_call(self, params) | |
1784 |
|
1785 | |||
1785 | expected = 'failed to edit permission for user group: `%s` in repo: `%s`' % ( |
|
1786 | expected = 'failed to edit permission for user group: `%s` in repo: `%s`' % ( | |
1786 | TEST_USER_GROUP, self.REPO |
|
1787 | TEST_USER_GROUP, self.REPO | |
1787 | ) |
|
1788 | ) | |
1788 | self._compare_error(id_, expected, given=response.body) |
|
1789 | self._compare_error(id_, expected, given=response.body) | |
1789 |
|
1790 | |||
1790 | @base.parametrize('name,perm,apply_to_children', [ |
|
1791 | @base.parametrize('name,perm,apply_to_children', [ | |
1791 | ('none', 'group.none', 'none'), |
|
1792 | ('none', 'group.none', 'none'), | |
1792 | ('read', 'group.read', 'none'), |
|
1793 | ('read', 'group.read', 'none'), | |
1793 | ('write', 'group.write', 'none'), |
|
1794 | ('write', 'group.write', 'none'), | |
1794 | ('admin', 'group.admin', 'none'), |
|
1795 | ('admin', 'group.admin', 'none'), | |
1795 |
|
1796 | |||
1796 | ('none', 'group.none', 'all'), |
|
1797 | ('none', 'group.none', 'all'), | |
1797 | ('read', 'group.read', 'all'), |
|
1798 | ('read', 'group.read', 'all'), | |
1798 | ('write', 'group.write', 'all'), |
|
1799 | ('write', 'group.write', 'all'), | |
1799 | ('admin', 'group.admin', 'all'), |
|
1800 | ('admin', 'group.admin', 'all'), | |
1800 |
|
1801 | |||
1801 | ('none', 'group.none', 'repos'), |
|
1802 | ('none', 'group.none', 'repos'), | |
1802 | ('read', 'group.read', 'repos'), |
|
1803 | ('read', 'group.read', 'repos'), | |
1803 | ('write', 'group.write', 'repos'), |
|
1804 | ('write', 'group.write', 'repos'), | |
1804 | ('admin', 'group.admin', 'repos'), |
|
1805 | ('admin', 'group.admin', 'repos'), | |
1805 |
|
1806 | |||
1806 | ('none', 'group.none', 'groups'), |
|
1807 | ('none', 'group.none', 'groups'), | |
1807 | ('read', 'group.read', 'groups'), |
|
1808 | ('read', 'group.read', 'groups'), | |
1808 | ('write', 'group.write', 'groups'), |
|
1809 | ('write', 'group.write', 'groups'), | |
1809 | ('admin', 'group.admin', 'groups'), |
|
1810 | ('admin', 'group.admin', 'groups'), | |
1810 | ]) |
|
1811 | ]) | |
1811 | def test_api_grant_user_permission_to_repo_group(self, name, perm, apply_to_children): |
|
1812 | def test_api_grant_user_permission_to_repo_group(self, name, perm, apply_to_children): | |
1812 | id_, params = _build_data(self.apikey, |
|
1813 | id_, params = _build_data(self.apikey, | |
1813 | 'grant_user_permission_to_repo_group', |
|
1814 | 'grant_user_permission_to_repo_group', | |
1814 | repogroupid=TEST_REPO_GROUP, |
|
1815 | repogroupid=TEST_REPO_GROUP, | |
1815 | userid=base.TEST_USER_ADMIN_LOGIN, |
|
1816 | userid=base.TEST_USER_ADMIN_LOGIN, | |
1816 | perm=perm, apply_to_children=apply_to_children) |
|
1817 | perm=perm, apply_to_children=apply_to_children) | |
1817 | response = api_call(self, params) |
|
1818 | response = api_call(self, params) | |
1818 |
|
1819 | |||
1819 | ret = { |
|
1820 | ret = { | |
1820 | 'msg': 'Granted perm: `%s` (recursive:%s) for user: `%s` in repo group: `%s`' % ( |
|
1821 | 'msg': 'Granted perm: `%s` (recursive:%s) for user: `%s` in repo group: `%s`' % ( | |
1821 | perm, apply_to_children, base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP |
|
1822 | perm, apply_to_children, base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP | |
1822 | ), |
|
1823 | ), | |
1823 | 'success': True |
|
1824 | 'success': True | |
1824 | } |
|
1825 | } | |
1825 | expected = ret |
|
1826 | expected = ret | |
1826 | self._compare_ok(id_, expected, given=response.body) |
|
1827 | self._compare_ok(id_, expected, given=response.body) | |
1827 |
|
1828 | |||
1828 | @base.parametrize('name,perm,apply_to_children,grant_admin,access_ok', [ |
|
1829 | @base.parametrize('name,perm,apply_to_children,grant_admin,access_ok', [ | |
1829 | ('none_fails', 'group.none', 'none', False, False), |
|
1830 | ('none_fails', 'group.none', 'none', False, False), | |
1830 | ('read_fails', 'group.read', 'none', False, False), |
|
1831 | ('read_fails', 'group.read', 'none', False, False), | |
1831 | ('write_fails', 'group.write', 'none', False, False), |
|
1832 | ('write_fails', 'group.write', 'none', False, False), | |
1832 | ('admin_fails', 'group.admin', 'none', False, False), |
|
1833 | ('admin_fails', 'group.admin', 'none', False, False), | |
1833 |
|
1834 | |||
1834 | # with granted perms |
|
1835 | # with granted perms | |
1835 | ('none_ok', 'group.none', 'none', True, True), |
|
1836 | ('none_ok', 'group.none', 'none', True, True), | |
1836 | ('read_ok', 'group.read', 'none', True, True), |
|
1837 | ('read_ok', 'group.read', 'none', True, True), | |
1837 | ('write_ok', 'group.write', 'none', True, True), |
|
1838 | ('write_ok', 'group.write', 'none', True, True), | |
1838 | ('admin_ok', 'group.admin', 'none', True, True), |
|
1839 | ('admin_ok', 'group.admin', 'none', True, True), | |
1839 | ]) |
|
1840 | ]) | |
1840 | def test_api_grant_user_permission_to_repo_group_by_regular_user( |
|
1841 | def test_api_grant_user_permission_to_repo_group_by_regular_user( | |
1841 | self, name, perm, apply_to_children, grant_admin, access_ok): |
|
1842 | self, name, perm, apply_to_children, grant_admin, access_ok): | |
1842 | if grant_admin: |
|
1843 | if grant_admin: | |
1843 | RepoGroupModel().grant_user_permission(TEST_REPO_GROUP, |
|
1844 | RepoGroupModel().grant_user_permission(TEST_REPO_GROUP, | |
1844 | self.TEST_USER_LOGIN, |
|
1845 | self.TEST_USER_LOGIN, | |
1845 | 'group.admin') |
|
1846 | 'group.admin') | |
1846 | meta.Session().commit() |
|
1847 | meta.Session().commit() | |
1847 |
|
1848 | |||
1848 | id_, params = _build_data(self.apikey_regular, |
|
1849 | id_, params = _build_data(self.apikey_regular, | |
1849 | 'grant_user_permission_to_repo_group', |
|
1850 | 'grant_user_permission_to_repo_group', | |
1850 | repogroupid=TEST_REPO_GROUP, |
|
1851 | repogroupid=TEST_REPO_GROUP, | |
1851 | userid=base.TEST_USER_ADMIN_LOGIN, |
|
1852 | userid=base.TEST_USER_ADMIN_LOGIN, | |
1852 | perm=perm, apply_to_children=apply_to_children) |
|
1853 | perm=perm, apply_to_children=apply_to_children) | |
1853 | response = api_call(self, params) |
|
1854 | response = api_call(self, params) | |
1854 | if access_ok: |
|
1855 | if access_ok: | |
1855 | ret = { |
|
1856 | ret = { | |
1856 | 'msg': 'Granted perm: `%s` (recursive:%s) for user: `%s` in repo group: `%s`' % ( |
|
1857 | 'msg': 'Granted perm: `%s` (recursive:%s) for user: `%s` in repo group: `%s`' % ( | |
1857 | perm, apply_to_children, base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP |
|
1858 | perm, apply_to_children, base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP | |
1858 | ), |
|
1859 | ), | |
1859 | 'success': True |
|
1860 | 'success': True | |
1860 | } |
|
1861 | } | |
1861 | expected = ret |
|
1862 | expected = ret | |
1862 | self._compare_ok(id_, expected, given=response.body) |
|
1863 | self._compare_ok(id_, expected, given=response.body) | |
1863 | else: |
|
1864 | else: | |
1864 | expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP |
|
1865 | expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP | |
1865 | self._compare_error(id_, expected, given=response.body) |
|
1866 | self._compare_error(id_, expected, given=response.body) | |
1866 |
|
1867 | |||
1867 | def test_api_grant_user_permission_to_repo_group_wrong_permission(self): |
|
1868 | def test_api_grant_user_permission_to_repo_group_wrong_permission(self): | |
1868 | perm = 'haha.no.permission' |
|
1869 | perm = 'haha.no.permission' | |
1869 | id_, params = _build_data(self.apikey, |
|
1870 | id_, params = _build_data(self.apikey, | |
1870 | 'grant_user_permission_to_repo_group', |
|
1871 | 'grant_user_permission_to_repo_group', | |
1871 | repogroupid=TEST_REPO_GROUP, |
|
1872 | repogroupid=TEST_REPO_GROUP, | |
1872 | userid=base.TEST_USER_ADMIN_LOGIN, |
|
1873 | userid=base.TEST_USER_ADMIN_LOGIN, | |
1873 | perm=perm) |
|
1874 | perm=perm) | |
1874 | response = api_call(self, params) |
|
1875 | response = api_call(self, params) | |
1875 |
|
1876 | |||
1876 | expected = 'permission `%s` does not exist' % perm |
|
1877 | expected = 'permission `%s` does not exist' % perm | |
1877 | self._compare_error(id_, expected, given=response.body) |
|
1878 | self._compare_error(id_, expected, given=response.body) | |
1878 |
|
1879 | |||
1879 | @mock.patch.object(RepoGroupModel, 'grant_user_permission', raise_exception) |
|
1880 | @mock.patch.object(RepoGroupModel, 'grant_user_permission', raise_exception) | |
1880 | def test_api_grant_user_permission_to_repo_group_exception_when_adding(self): |
|
1881 | def test_api_grant_user_permission_to_repo_group_exception_when_adding(self): | |
1881 | perm = 'group.read' |
|
1882 | perm = 'group.read' | |
1882 | id_, params = _build_data(self.apikey, |
|
1883 | id_, params = _build_data(self.apikey, | |
1883 | 'grant_user_permission_to_repo_group', |
|
1884 | 'grant_user_permission_to_repo_group', | |
1884 | repogroupid=TEST_REPO_GROUP, |
|
1885 | repogroupid=TEST_REPO_GROUP, | |
1885 | userid=base.TEST_USER_ADMIN_LOGIN, |
|
1886 | userid=base.TEST_USER_ADMIN_LOGIN, | |
1886 | perm=perm) |
|
1887 | perm=perm) | |
1887 | response = api_call(self, params) |
|
1888 | response = api_call(self, params) | |
1888 |
|
1889 | |||
1889 | expected = 'failed to edit permission for user: `%s` in repo group: `%s`' % ( |
|
1890 | expected = 'failed to edit permission for user: `%s` in repo group: `%s`' % ( | |
1890 | base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP |
|
1891 | base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP | |
1891 | ) |
|
1892 | ) | |
1892 | self._compare_error(id_, expected, given=response.body) |
|
1893 | self._compare_error(id_, expected, given=response.body) | |
1893 |
|
1894 | |||
1894 | @base.parametrize('name,apply_to_children', [ |
|
1895 | @base.parametrize('name,apply_to_children', [ | |
1895 | ('none', 'none'), |
|
1896 | ('none', 'none'), | |
1896 | ('all', 'all'), |
|
1897 | ('all', 'all'), | |
1897 | ('repos', 'repos'), |
|
1898 | ('repos', 'repos'), | |
1898 | ('groups', 'groups'), |
|
1899 | ('groups', 'groups'), | |
1899 | ]) |
|
1900 | ]) | |
1900 | def test_api_revoke_user_permission_from_repo_group(self, name, apply_to_children): |
|
1901 | def test_api_revoke_user_permission_from_repo_group(self, name, apply_to_children): | |
1901 | RepoGroupModel().grant_user_permission(repo_group=TEST_REPO_GROUP, |
|
1902 | RepoGroupModel().grant_user_permission(repo_group=TEST_REPO_GROUP, | |
1902 | user=base.TEST_USER_ADMIN_LOGIN, |
|
1903 | user=base.TEST_USER_ADMIN_LOGIN, | |
1903 | perm='group.read',) |
|
1904 | perm='group.read',) | |
1904 | meta.Session().commit() |
|
1905 | meta.Session().commit() | |
1905 |
|
1906 | |||
1906 | id_, params = _build_data(self.apikey, |
|
1907 | id_, params = _build_data(self.apikey, | |
1907 | 'revoke_user_permission_from_repo_group', |
|
1908 | 'revoke_user_permission_from_repo_group', | |
1908 | repogroupid=TEST_REPO_GROUP, |
|
1909 | repogroupid=TEST_REPO_GROUP, | |
1909 | userid=base.TEST_USER_ADMIN_LOGIN, |
|
1910 | userid=base.TEST_USER_ADMIN_LOGIN, | |
1910 | apply_to_children=apply_to_children,) |
|
1911 | apply_to_children=apply_to_children,) | |
1911 | response = api_call(self, params) |
|
1912 | response = api_call(self, params) | |
1912 |
|
1913 | |||
1913 | expected = { |
|
1914 | expected = { | |
1914 | 'msg': 'Revoked perm (recursive:%s) for user: `%s` in repo group: `%s`' % ( |
|
1915 | 'msg': 'Revoked perm (recursive:%s) for user: `%s` in repo group: `%s`' % ( | |
1915 | apply_to_children, base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP |
|
1916 | apply_to_children, base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP | |
1916 | ), |
|
1917 | ), | |
1917 | 'success': True |
|
1918 | 'success': True | |
1918 | } |
|
1919 | } | |
1919 | self._compare_ok(id_, expected, given=response.body) |
|
1920 | self._compare_ok(id_, expected, given=response.body) | |
1920 |
|
1921 | |||
1921 | @base.parametrize('name,apply_to_children,grant_admin,access_ok', [ |
|
1922 | @base.parametrize('name,apply_to_children,grant_admin,access_ok', [ | |
1922 | ('none', 'none', False, False), |
|
1923 | ('none', 'none', False, False), | |
1923 | ('all', 'all', False, False), |
|
1924 | ('all', 'all', False, False), | |
1924 | ('repos', 'repos', False, False), |
|
1925 | ('repos', 'repos', False, False), | |
1925 | ('groups', 'groups', False, False), |
|
1926 | ('groups', 'groups', False, False), | |
1926 |
|
1927 | |||
1927 | # after granting admin rights |
|
1928 | # after granting admin rights | |
1928 | ('none', 'none', False, False), |
|
1929 | ('none', 'none', False, False), | |
1929 | ('all', 'all', False, False), |
|
1930 | ('all', 'all', False, False), | |
1930 | ('repos', 'repos', False, False), |
|
1931 | ('repos', 'repos', False, False), | |
1931 | ('groups', 'groups', False, False), |
|
1932 | ('groups', 'groups', False, False), | |
1932 | ]) |
|
1933 | ]) | |
1933 | def test_api_revoke_user_permission_from_repo_group_by_regular_user( |
|
1934 | def test_api_revoke_user_permission_from_repo_group_by_regular_user( | |
1934 | self, name, apply_to_children, grant_admin, access_ok): |
|
1935 | self, name, apply_to_children, grant_admin, access_ok): | |
1935 | RepoGroupModel().grant_user_permission(repo_group=TEST_REPO_GROUP, |
|
1936 | RepoGroupModel().grant_user_permission(repo_group=TEST_REPO_GROUP, | |
1936 | user=base.TEST_USER_ADMIN_LOGIN, |
|
1937 | user=base.TEST_USER_ADMIN_LOGIN, | |
1937 | perm='group.read',) |
|
1938 | perm='group.read',) | |
1938 | meta.Session().commit() |
|
1939 | meta.Session().commit() | |
1939 |
|
1940 | |||
1940 | if grant_admin: |
|
1941 | if grant_admin: | |
1941 | RepoGroupModel().grant_user_permission(TEST_REPO_GROUP, |
|
1942 | RepoGroupModel().grant_user_permission(TEST_REPO_GROUP, | |
1942 | self.TEST_USER_LOGIN, |
|
1943 | self.TEST_USER_LOGIN, | |
1943 | 'group.admin') |
|
1944 | 'group.admin') | |
1944 | meta.Session().commit() |
|
1945 | meta.Session().commit() | |
1945 |
|
1946 | |||
1946 | id_, params = _build_data(self.apikey_regular, |
|
1947 | id_, params = _build_data(self.apikey_regular, | |
1947 | 'revoke_user_permission_from_repo_group', |
|
1948 | 'revoke_user_permission_from_repo_group', | |
1948 | repogroupid=TEST_REPO_GROUP, |
|
1949 | repogroupid=TEST_REPO_GROUP, | |
1949 | userid=base.TEST_USER_ADMIN_LOGIN, |
|
1950 | userid=base.TEST_USER_ADMIN_LOGIN, | |
1950 | apply_to_children=apply_to_children,) |
|
1951 | apply_to_children=apply_to_children,) | |
1951 | response = api_call(self, params) |
|
1952 | response = api_call(self, params) | |
1952 | if access_ok: |
|
1953 | if access_ok: | |
1953 | expected = { |
|
1954 | expected = { | |
1954 | 'msg': 'Revoked perm (recursive:%s) for user: `%s` in repo group: `%s`' % ( |
|
1955 | 'msg': 'Revoked perm (recursive:%s) for user: `%s` in repo group: `%s`' % ( | |
1955 | apply_to_children, base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP |
|
1956 | apply_to_children, base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP | |
1956 | ), |
|
1957 | ), | |
1957 | 'success': True |
|
1958 | 'success': True | |
1958 | } |
|
1959 | } | |
1959 | self._compare_ok(id_, expected, given=response.body) |
|
1960 | self._compare_ok(id_, expected, given=response.body) | |
1960 | else: |
|
1961 | else: | |
1961 | expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP |
|
1962 | expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP | |
1962 | self._compare_error(id_, expected, given=response.body) |
|
1963 | self._compare_error(id_, expected, given=response.body) | |
1963 |
|
1964 | |||
1964 | @mock.patch.object(RepoGroupModel, 'revoke_user_permission', raise_exception) |
|
1965 | @mock.patch.object(RepoGroupModel, 'revoke_user_permission', raise_exception) | |
1965 | def test_api_revoke_user_permission_from_repo_group_exception_when_adding(self): |
|
1966 | def test_api_revoke_user_permission_from_repo_group_exception_when_adding(self): | |
1966 | id_, params = _build_data(self.apikey, |
|
1967 | id_, params = _build_data(self.apikey, | |
1967 | 'revoke_user_permission_from_repo_group', |
|
1968 | 'revoke_user_permission_from_repo_group', | |
1968 | repogroupid=TEST_REPO_GROUP, |
|
1969 | repogroupid=TEST_REPO_GROUP, | |
1969 | userid=base.TEST_USER_ADMIN_LOGIN, ) |
|
1970 | userid=base.TEST_USER_ADMIN_LOGIN, ) | |
1970 | response = api_call(self, params) |
|
1971 | response = api_call(self, params) | |
1971 |
|
1972 | |||
1972 | expected = 'failed to edit permission for user: `%s` in repo group: `%s`' % ( |
|
1973 | expected = 'failed to edit permission for user: `%s` in repo group: `%s`' % ( | |
1973 | base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP |
|
1974 | base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP | |
1974 | ) |
|
1975 | ) | |
1975 | self._compare_error(id_, expected, given=response.body) |
|
1976 | self._compare_error(id_, expected, given=response.body) | |
1976 |
|
1977 | |||
1977 | @base.parametrize('name,perm,apply_to_children', [ |
|
1978 | @base.parametrize('name,perm,apply_to_children', [ | |
1978 | ('none', 'group.none', 'none'), |
|
1979 | ('none', 'group.none', 'none'), | |
1979 | ('read', 'group.read', 'none'), |
|
1980 | ('read', 'group.read', 'none'), | |
1980 | ('write', 'group.write', 'none'), |
|
1981 | ('write', 'group.write', 'none'), | |
1981 | ('admin', 'group.admin', 'none'), |
|
1982 | ('admin', 'group.admin', 'none'), | |
1982 |
|
1983 | |||
1983 | ('none', 'group.none', 'all'), |
|
1984 | ('none', 'group.none', 'all'), | |
1984 | ('read', 'group.read', 'all'), |
|
1985 | ('read', 'group.read', 'all'), | |
1985 | ('write', 'group.write', 'all'), |
|
1986 | ('write', 'group.write', 'all'), | |
1986 | ('admin', 'group.admin', 'all'), |
|
1987 | ('admin', 'group.admin', 'all'), | |
1987 |
|
1988 | |||
1988 | ('none', 'group.none', 'repos'), |
|
1989 | ('none', 'group.none', 'repos'), | |
1989 | ('read', 'group.read', 'repos'), |
|
1990 | ('read', 'group.read', 'repos'), | |
1990 | ('write', 'group.write', 'repos'), |
|
1991 | ('write', 'group.write', 'repos'), | |
1991 | ('admin', 'group.admin', 'repos'), |
|
1992 | ('admin', 'group.admin', 'repos'), | |
1992 |
|
1993 | |||
1993 | ('none', 'group.none', 'groups'), |
|
1994 | ('none', 'group.none', 'groups'), | |
1994 | ('read', 'group.read', 'groups'), |
|
1995 | ('read', 'group.read', 'groups'), | |
1995 | ('write', 'group.write', 'groups'), |
|
1996 | ('write', 'group.write', 'groups'), | |
1996 | ('admin', 'group.admin', 'groups'), |
|
1997 | ('admin', 'group.admin', 'groups'), | |
1997 | ]) |
|
1998 | ]) | |
1998 | def test_api_grant_user_group_permission_to_repo_group(self, name, perm, apply_to_children): |
|
1999 | def test_api_grant_user_group_permission_to_repo_group(self, name, perm, apply_to_children): | |
1999 | id_, params = _build_data(self.apikey, |
|
2000 | id_, params = _build_data(self.apikey, | |
2000 | 'grant_user_group_permission_to_repo_group', |
|
2001 | 'grant_user_group_permission_to_repo_group', | |
2001 | repogroupid=TEST_REPO_GROUP, |
|
2002 | repogroupid=TEST_REPO_GROUP, | |
2002 | usergroupid=TEST_USER_GROUP, |
|
2003 | usergroupid=TEST_USER_GROUP, | |
2003 | perm=perm, |
|
2004 | perm=perm, | |
2004 | apply_to_children=apply_to_children,) |
|
2005 | apply_to_children=apply_to_children,) | |
2005 | response = api_call(self, params) |
|
2006 | response = api_call(self, params) | |
2006 |
|
2007 | |||
2007 | ret = { |
|
2008 | ret = { | |
2008 | 'msg': 'Granted perm: `%s` (recursive:%s) for user group: `%s` in repo group: `%s`' % ( |
|
2009 | 'msg': 'Granted perm: `%s` (recursive:%s) for user group: `%s` in repo group: `%s`' % ( | |
2009 | perm, apply_to_children, TEST_USER_GROUP, TEST_REPO_GROUP |
|
2010 | perm, apply_to_children, TEST_USER_GROUP, TEST_REPO_GROUP | |
2010 | ), |
|
2011 | ), | |
2011 | 'success': True |
|
2012 | 'success': True | |
2012 | } |
|
2013 | } | |
2013 | expected = ret |
|
2014 | expected = ret | |
2014 | self._compare_ok(id_, expected, given=response.body) |
|
2015 | self._compare_ok(id_, expected, given=response.body) | |
2015 |
|
2016 | |||
2016 | @base.parametrize('name,perm,apply_to_children,grant_admin,access_ok', [ |
|
2017 | @base.parametrize('name,perm,apply_to_children,grant_admin,access_ok', [ | |
2017 | ('none_fails', 'group.none', 'none', False, False), |
|
2018 | ('none_fails', 'group.none', 'none', False, False), | |
2018 | ('read_fails', 'group.read', 'none', False, False), |
|
2019 | ('read_fails', 'group.read', 'none', False, False), | |
2019 | ('write_fails', 'group.write', 'none', False, False), |
|
2020 | ('write_fails', 'group.write', 'none', False, False), | |
2020 | ('admin_fails', 'group.admin', 'none', False, False), |
|
2021 | ('admin_fails', 'group.admin', 'none', False, False), | |
2021 |
|
2022 | |||
2022 | # with granted perms |
|
2023 | # with granted perms | |
2023 | ('none_ok', 'group.none', 'none', True, True), |
|
2024 | ('none_ok', 'group.none', 'none', True, True), | |
2024 | ('read_ok', 'group.read', 'none', True, True), |
|
2025 | ('read_ok', 'group.read', 'none', True, True), | |
2025 | ('write_ok', 'group.write', 'none', True, True), |
|
2026 | ('write_ok', 'group.write', 'none', True, True), | |
2026 | ('admin_ok', 'group.admin', 'none', True, True), |
|
2027 | ('admin_ok', 'group.admin', 'none', True, True), | |
2027 | ]) |
|
2028 | ]) | |
2028 | def test_api_grant_user_group_permission_to_repo_group_by_regular_user( |
|
2029 | def test_api_grant_user_group_permission_to_repo_group_by_regular_user( | |
2029 | self, name, perm, apply_to_children, grant_admin, access_ok): |
|
2030 | self, name, perm, apply_to_children, grant_admin, access_ok): | |
2030 | if grant_admin: |
|
2031 | if grant_admin: | |
2031 | RepoGroupModel().grant_user_permission(TEST_REPO_GROUP, |
|
2032 | RepoGroupModel().grant_user_permission(TEST_REPO_GROUP, | |
2032 | self.TEST_USER_LOGIN, |
|
2033 | self.TEST_USER_LOGIN, | |
2033 | 'group.admin') |
|
2034 | 'group.admin') | |
2034 | meta.Session().commit() |
|
2035 | meta.Session().commit() | |
2035 |
|
2036 | |||
2036 | id_, params = _build_data(self.apikey_regular, |
|
2037 | id_, params = _build_data(self.apikey_regular, | |
2037 | 'grant_user_group_permission_to_repo_group', |
|
2038 | 'grant_user_group_permission_to_repo_group', | |
2038 | repogroupid=TEST_REPO_GROUP, |
|
2039 | repogroupid=TEST_REPO_GROUP, | |
2039 | usergroupid=TEST_USER_GROUP, |
|
2040 | usergroupid=TEST_USER_GROUP, | |
2040 | perm=perm, |
|
2041 | perm=perm, | |
2041 | apply_to_children=apply_to_children,) |
|
2042 | apply_to_children=apply_to_children,) | |
2042 | response = api_call(self, params) |
|
2043 | response = api_call(self, params) | |
2043 | if access_ok: |
|
2044 | if access_ok: | |
2044 | ret = { |
|
2045 | ret = { | |
2045 | 'msg': 'Granted perm: `%s` (recursive:%s) for user group: `%s` in repo group: `%s`' % ( |
|
2046 | 'msg': 'Granted perm: `%s` (recursive:%s) for user group: `%s` in repo group: `%s`' % ( | |
2046 | perm, apply_to_children, TEST_USER_GROUP, TEST_REPO_GROUP |
|
2047 | perm, apply_to_children, TEST_USER_GROUP, TEST_REPO_GROUP | |
2047 | ), |
|
2048 | ), | |
2048 | 'success': True |
|
2049 | 'success': True | |
2049 | } |
|
2050 | } | |
2050 | expected = ret |
|
2051 | expected = ret | |
2051 | self._compare_ok(id_, expected, given=response.body) |
|
2052 | self._compare_ok(id_, expected, given=response.body) | |
2052 | else: |
|
2053 | else: | |
2053 | expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP |
|
2054 | expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP | |
2054 | self._compare_error(id_, expected, given=response.body) |
|
2055 | self._compare_error(id_, expected, given=response.body) | |
2055 |
|
2056 | |||
2056 | def test_api_grant_user_group_permission_to_repo_group_wrong_permission(self): |
|
2057 | def test_api_grant_user_group_permission_to_repo_group_wrong_permission(self): | |
2057 | perm = 'haha.no.permission' |
|
2058 | perm = 'haha.no.permission' | |
2058 | id_, params = _build_data(self.apikey, |
|
2059 | id_, params = _build_data(self.apikey, | |
2059 | 'grant_user_group_permission_to_repo_group', |
|
2060 | 'grant_user_group_permission_to_repo_group', | |
2060 | repogroupid=TEST_REPO_GROUP, |
|
2061 | repogroupid=TEST_REPO_GROUP, | |
2061 | usergroupid=TEST_USER_GROUP, |
|
2062 | usergroupid=TEST_USER_GROUP, | |
2062 | perm=perm) |
|
2063 | perm=perm) | |
2063 | response = api_call(self, params) |
|
2064 | response = api_call(self, params) | |
2064 |
|
2065 | |||
2065 | expected = 'permission `%s` does not exist' % perm |
|
2066 | expected = 'permission `%s` does not exist' % perm | |
2066 | self._compare_error(id_, expected, given=response.body) |
|
2067 | self._compare_error(id_, expected, given=response.body) | |
2067 |
|
2068 | |||
2068 | @mock.patch.object(RepoGroupModel, 'grant_user_group_permission', raise_exception) |
|
2069 | @mock.patch.object(RepoGroupModel, 'grant_user_group_permission', raise_exception) | |
2069 | def test_api_grant_user_group_permission_exception_when_adding_to_repo_group(self): |
|
2070 | def test_api_grant_user_group_permission_exception_when_adding_to_repo_group(self): | |
2070 | perm = 'group.read' |
|
2071 | perm = 'group.read' | |
2071 | id_, params = _build_data(self.apikey, |
|
2072 | id_, params = _build_data(self.apikey, | |
2072 | 'grant_user_group_permission_to_repo_group', |
|
2073 | 'grant_user_group_permission_to_repo_group', | |
2073 | repogroupid=TEST_REPO_GROUP, |
|
2074 | repogroupid=TEST_REPO_GROUP, | |
2074 | usergroupid=TEST_USER_GROUP, |
|
2075 | usergroupid=TEST_USER_GROUP, | |
2075 | perm=perm) |
|
2076 | perm=perm) | |
2076 | response = api_call(self, params) |
|
2077 | response = api_call(self, params) | |
2077 |
|
2078 | |||
2078 | expected = 'failed to edit permission for user group: `%s` in repo group: `%s`' % ( |
|
2079 | expected = 'failed to edit permission for user group: `%s` in repo group: `%s`' % ( | |
2079 | TEST_USER_GROUP, TEST_REPO_GROUP |
|
2080 | TEST_USER_GROUP, TEST_REPO_GROUP | |
2080 | ) |
|
2081 | ) | |
2081 | self._compare_error(id_, expected, given=response.body) |
|
2082 | self._compare_error(id_, expected, given=response.body) | |
2082 |
|
2083 | |||
2083 | @base.parametrize('name,apply_to_children', [ |
|
2084 | @base.parametrize('name,apply_to_children', [ | |
2084 | ('none', 'none'), |
|
2085 | ('none', 'none'), | |
2085 | ('all', 'all'), |
|
2086 | ('all', 'all'), | |
2086 | ('repos', 'repos'), |
|
2087 | ('repos', 'repos'), | |
2087 | ('groups', 'groups'), |
|
2088 | ('groups', 'groups'), | |
2088 | ]) |
|
2089 | ]) | |
2089 | def test_api_revoke_user_group_permission_from_repo_group(self, name, apply_to_children): |
|
2090 | def test_api_revoke_user_group_permission_from_repo_group(self, name, apply_to_children): | |
2090 | RepoGroupModel().grant_user_group_permission(repo_group=TEST_REPO_GROUP, |
|
2091 | RepoGroupModel().grant_user_group_permission(repo_group=TEST_REPO_GROUP, | |
2091 | group_name=TEST_USER_GROUP, |
|
2092 | group_name=TEST_USER_GROUP, | |
2092 | perm='group.read',) |
|
2093 | perm='group.read',) | |
2093 | meta.Session().commit() |
|
2094 | meta.Session().commit() | |
2094 | id_, params = _build_data(self.apikey, |
|
2095 | id_, params = _build_data(self.apikey, | |
2095 | 'revoke_user_group_permission_from_repo_group', |
|
2096 | 'revoke_user_group_permission_from_repo_group', | |
2096 | repogroupid=TEST_REPO_GROUP, |
|
2097 | repogroupid=TEST_REPO_GROUP, | |
2097 | usergroupid=TEST_USER_GROUP, |
|
2098 | usergroupid=TEST_USER_GROUP, | |
2098 | apply_to_children=apply_to_children,) |
|
2099 | apply_to_children=apply_to_children,) | |
2099 | response = api_call(self, params) |
|
2100 | response = api_call(self, params) | |
2100 |
|
2101 | |||
2101 | expected = { |
|
2102 | expected = { | |
2102 | 'msg': 'Revoked perm (recursive:%s) for user group: `%s` in repo group: `%s`' % ( |
|
2103 | 'msg': 'Revoked perm (recursive:%s) for user group: `%s` in repo group: `%s`' % ( | |
2103 | apply_to_children, TEST_USER_GROUP, TEST_REPO_GROUP |
|
2104 | apply_to_children, TEST_USER_GROUP, TEST_REPO_GROUP | |
2104 | ), |
|
2105 | ), | |
2105 | 'success': True |
|
2106 | 'success': True | |
2106 | } |
|
2107 | } | |
2107 | self._compare_ok(id_, expected, given=response.body) |
|
2108 | self._compare_ok(id_, expected, given=response.body) | |
2108 |
|
2109 | |||
2109 | @base.parametrize('name,apply_to_children,grant_admin,access_ok', [ |
|
2110 | @base.parametrize('name,apply_to_children,grant_admin,access_ok', [ | |
2110 | ('none', 'none', False, False), |
|
2111 | ('none', 'none', False, False), | |
2111 | ('all', 'all', False, False), |
|
2112 | ('all', 'all', False, False), | |
2112 | ('repos', 'repos', False, False), |
|
2113 | ('repos', 'repos', False, False), | |
2113 | ('groups', 'groups', False, False), |
|
2114 | ('groups', 'groups', False, False), | |
2114 |
|
2115 | |||
2115 | # after granting admin rights |
|
2116 | # after granting admin rights | |
2116 | ('none', 'none', False, False), |
|
2117 | ('none', 'none', False, False), | |
2117 | ('all', 'all', False, False), |
|
2118 | ('all', 'all', False, False), | |
2118 | ('repos', 'repos', False, False), |
|
2119 | ('repos', 'repos', False, False), | |
2119 | ('groups', 'groups', False, False), |
|
2120 | ('groups', 'groups', False, False), | |
2120 | ]) |
|
2121 | ]) | |
2121 | def test_api_revoke_user_group_permission_from_repo_group_by_regular_user( |
|
2122 | def test_api_revoke_user_group_permission_from_repo_group_by_regular_user( | |
2122 | self, name, apply_to_children, grant_admin, access_ok): |
|
2123 | self, name, apply_to_children, grant_admin, access_ok): | |
2123 | RepoGroupModel().grant_user_permission(repo_group=TEST_REPO_GROUP, |
|
2124 | RepoGroupModel().grant_user_permission(repo_group=TEST_REPO_GROUP, | |
2124 | user=base.TEST_USER_ADMIN_LOGIN, |
|
2125 | user=base.TEST_USER_ADMIN_LOGIN, | |
2125 | perm='group.read',) |
|
2126 | perm='group.read',) | |
2126 | meta.Session().commit() |
|
2127 | meta.Session().commit() | |
2127 |
|
2128 | |||
2128 | if grant_admin: |
|
2129 | if grant_admin: | |
2129 | RepoGroupModel().grant_user_permission(TEST_REPO_GROUP, |
|
2130 | RepoGroupModel().grant_user_permission(TEST_REPO_GROUP, | |
2130 | self.TEST_USER_LOGIN, |
|
2131 | self.TEST_USER_LOGIN, | |
2131 | 'group.admin') |
|
2132 | 'group.admin') | |
2132 | meta.Session().commit() |
|
2133 | meta.Session().commit() | |
2133 |
|
2134 | |||
2134 | id_, params = _build_data(self.apikey_regular, |
|
2135 | id_, params = _build_data(self.apikey_regular, | |
2135 | 'revoke_user_group_permission_from_repo_group', |
|
2136 | 'revoke_user_group_permission_from_repo_group', | |
2136 | repogroupid=TEST_REPO_GROUP, |
|
2137 | repogroupid=TEST_REPO_GROUP, | |
2137 | usergroupid=TEST_USER_GROUP, |
|
2138 | usergroupid=TEST_USER_GROUP, | |
2138 | apply_to_children=apply_to_children,) |
|
2139 | apply_to_children=apply_to_children,) | |
2139 | response = api_call(self, params) |
|
2140 | response = api_call(self, params) | |
2140 | if access_ok: |
|
2141 | if access_ok: | |
2141 | expected = { |
|
2142 | expected = { | |
2142 | 'msg': 'Revoked perm (recursive:%s) for user group: `%s` in repo group: `%s`' % ( |
|
2143 | 'msg': 'Revoked perm (recursive:%s) for user group: `%s` in repo group: `%s`' % ( | |
2143 | apply_to_children, base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP |
|
2144 | apply_to_children, base.TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP | |
2144 | ), |
|
2145 | ), | |
2145 | 'success': True |
|
2146 | 'success': True | |
2146 | } |
|
2147 | } | |
2147 | self._compare_ok(id_, expected, given=response.body) |
|
2148 | self._compare_ok(id_, expected, given=response.body) | |
2148 | else: |
|
2149 | else: | |
2149 | expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP |
|
2150 | expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP | |
2150 | self._compare_error(id_, expected, given=response.body) |
|
2151 | self._compare_error(id_, expected, given=response.body) | |
2151 |
|
2152 | |||
2152 | @mock.patch.object(RepoGroupModel, 'revoke_user_group_permission', raise_exception) |
|
2153 | @mock.patch.object(RepoGroupModel, 'revoke_user_group_permission', raise_exception) | |
2153 | def test_api_revoke_user_group_permission_from_repo_group_exception_when_adding(self): |
|
2154 | def test_api_revoke_user_group_permission_from_repo_group_exception_when_adding(self): | |
2154 | id_, params = _build_data(self.apikey, 'revoke_user_group_permission_from_repo_group', |
|
2155 | id_, params = _build_data(self.apikey, 'revoke_user_group_permission_from_repo_group', | |
2155 | repogroupid=TEST_REPO_GROUP, |
|
2156 | repogroupid=TEST_REPO_GROUP, | |
2156 | usergroupid=TEST_USER_GROUP,) |
|
2157 | usergroupid=TEST_USER_GROUP,) | |
2157 | response = api_call(self, params) |
|
2158 | response = api_call(self, params) | |
2158 |
|
2159 | |||
2159 | expected = 'failed to edit permission for user group: `%s` in repo group: `%s`' % ( |
|
2160 | expected = 'failed to edit permission for user group: `%s` in repo group: `%s`' % ( | |
2160 | TEST_USER_GROUP, TEST_REPO_GROUP |
|
2161 | TEST_USER_GROUP, TEST_REPO_GROUP | |
2161 | ) |
|
2162 | ) | |
2162 | self._compare_error(id_, expected, given=response.body) |
|
2163 | self._compare_error(id_, expected, given=response.body) | |
2163 |
|
2164 | |||
2164 | def test_api_get_gist(self): |
|
2165 | def test_api_get_gist(self): | |
2165 | gist = fixture.create_gist() |
|
2166 | gist = fixture.create_gist() | |
2166 | gist_id = gist.gist_access_id |
|
2167 | gist_id = gist.gist_access_id | |
2167 | gist_created_on = gist.created_on |
|
2168 | gist_created_on = gist.created_on | |
2168 | id_, params = _build_data(self.apikey, 'get_gist', |
|
2169 | id_, params = _build_data(self.apikey, 'get_gist', | |
2169 | gistid=gist_id, ) |
|
2170 | gistid=gist_id, ) | |
2170 | response = api_call(self, params) |
|
2171 | response = api_call(self, params) | |
2171 |
|
2172 | |||
2172 | expected = { |
|
2173 | expected = { | |
2173 | 'access_id': gist_id, |
|
2174 | 'access_id': gist_id, | |
2174 | 'created_on': gist_created_on, |
|
2175 | 'created_on': gist_created_on, | |
2175 | 'description': 'new-gist', |
|
2176 | 'description': 'new-gist', | |
2176 | 'expires': -1.0, |
|
2177 | 'expires': -1.0, | |
2177 | 'gist_id': int(gist_id), |
|
2178 | 'gist_id': int(gist_id), | |
2178 | 'type': 'public', |
|
2179 | 'type': 'public', | |
2179 | 'url': 'http://localhost:80/_admin/gists/%s' % gist_id |
|
2180 | 'url': 'http://localhost:80/_admin/gists/%s' % gist_id | |
2180 | } |
|
2181 | } | |
2181 |
|
2182 | |||
2182 | self._compare_ok(id_, expected, given=response.body) |
|
2183 | self._compare_ok(id_, expected, given=response.body) | |
2183 |
|
2184 | |||
2184 | def test_api_get_gist_that_does_not_exist(self): |
|
2185 | def test_api_get_gist_that_does_not_exist(self): | |
2185 | id_, params = _build_data(self.apikey_regular, 'get_gist', |
|
2186 | id_, params = _build_data(self.apikey_regular, 'get_gist', | |
2186 | gistid='12345', ) |
|
2187 | gistid='12345', ) | |
2187 | response = api_call(self, params) |
|
2188 | response = api_call(self, params) | |
2188 | expected = 'gist `%s` does not exist' % ('12345',) |
|
2189 | expected = 'gist `%s` does not exist' % ('12345',) | |
2189 | self._compare_error(id_, expected, given=response.body) |
|
2190 | self._compare_error(id_, expected, given=response.body) | |
2190 |
|
2191 | |||
2191 | def test_api_get_gist_private_gist_without_permission(self): |
|
2192 | def test_api_get_gist_private_gist_without_permission(self): | |
2192 | gist = fixture.create_gist() |
|
2193 | gist = fixture.create_gist() | |
2193 | gist_id = gist.gist_access_id |
|
2194 | gist_id = gist.gist_access_id | |
2194 | gist_created_on = gist.created_on |
|
2195 | gist_created_on = gist.created_on | |
2195 | id_, params = _build_data(self.apikey_regular, 'get_gist', |
|
2196 | id_, params = _build_data(self.apikey_regular, 'get_gist', | |
2196 | gistid=gist_id, ) |
|
2197 | gistid=gist_id, ) | |
2197 | response = api_call(self, params) |
|
2198 | response = api_call(self, params) | |
2198 |
|
2199 | |||
2199 | expected = 'gist `%s` does not exist' % gist_id |
|
2200 | expected = 'gist `%s` does not exist' % gist_id | |
2200 | self._compare_error(id_, expected, given=response.body) |
|
2201 | self._compare_error(id_, expected, given=response.body) | |
2201 |
|
2202 | |||
2202 | def test_api_get_gists(self): |
|
2203 | def test_api_get_gists(self): | |
2203 | fixture.create_gist() |
|
2204 | fixture.create_gist() | |
2204 | fixture.create_gist() |
|
2205 | fixture.create_gist() | |
2205 |
|
2206 | |||
2206 | id_, params = _build_data(self.apikey, 'get_gists') |
|
2207 | id_, params = _build_data(self.apikey, 'get_gists') | |
2207 | response = api_call(self, params) |
|
2208 | response = api_call(self, params) | |
2208 | expected = response.json |
|
2209 | expected = response.json | |
2209 | assert len(response.json['result']) == 2 |
|
2210 | assert len(response.json['result']) == 2 | |
2210 | #self._compare_ok(id_, expected, given=response.body) |
|
2211 | #self._compare_ok(id_, expected, given=response.body) | |
2211 |
|
2212 | |||
2212 | def test_api_get_gists_regular_user(self): |
|
2213 | def test_api_get_gists_regular_user(self): | |
2213 | # by admin |
|
2214 | # by admin | |
2214 | fixture.create_gist() |
|
2215 | fixture.create_gist() | |
2215 | fixture.create_gist() |
|
2216 | fixture.create_gist() | |
2216 |
|
2217 | |||
2217 | # by reg user |
|
2218 | # by reg user | |
2218 | fixture.create_gist(owner=self.TEST_USER_LOGIN) |
|
2219 | fixture.create_gist(owner=self.TEST_USER_LOGIN) | |
2219 | fixture.create_gist(owner=self.TEST_USER_LOGIN) |
|
2220 | fixture.create_gist(owner=self.TEST_USER_LOGIN) | |
2220 | fixture.create_gist(owner=self.TEST_USER_LOGIN) |
|
2221 | fixture.create_gist(owner=self.TEST_USER_LOGIN) | |
2221 |
|
2222 | |||
2222 | id_, params = _build_data(self.apikey_regular, 'get_gists') |
|
2223 | id_, params = _build_data(self.apikey_regular, 'get_gists') | |
2223 | response = api_call(self, params) |
|
2224 | response = api_call(self, params) | |
2224 | expected = response.json |
|
2225 | expected = response.json | |
2225 | assert len(response.json['result']) == 3 |
|
2226 | assert len(response.json['result']) == 3 | |
2226 | #self._compare_ok(id_, expected, given=response.body) |
|
2227 | #self._compare_ok(id_, expected, given=response.body) | |
2227 |
|
2228 | |||
2228 | def test_api_get_gists_only_for_regular_user(self): |
|
2229 | def test_api_get_gists_only_for_regular_user(self): | |
2229 | # by admin |
|
2230 | # by admin | |
2230 | fixture.create_gist() |
|
2231 | fixture.create_gist() | |
2231 | fixture.create_gist() |
|
2232 | fixture.create_gist() | |
2232 |
|
2233 | |||
2233 | # by reg user |
|
2234 | # by reg user | |
2234 | fixture.create_gist(owner=self.TEST_USER_LOGIN) |
|
2235 | fixture.create_gist(owner=self.TEST_USER_LOGIN) | |
2235 | fixture.create_gist(owner=self.TEST_USER_LOGIN) |
|
2236 | fixture.create_gist(owner=self.TEST_USER_LOGIN) | |
2236 | fixture.create_gist(owner=self.TEST_USER_LOGIN) |
|
2237 | fixture.create_gist(owner=self.TEST_USER_LOGIN) | |
2237 |
|
2238 | |||
2238 | id_, params = _build_data(self.apikey, 'get_gists', |
|
2239 | id_, params = _build_data(self.apikey, 'get_gists', | |
2239 | userid=self.TEST_USER_LOGIN) |
|
2240 | userid=self.TEST_USER_LOGIN) | |
2240 | response = api_call(self, params) |
|
2241 | response = api_call(self, params) | |
2241 | expected = response.json |
|
2242 | expected = response.json | |
2242 | assert len(response.json['result']) == 3 |
|
2243 | assert len(response.json['result']) == 3 | |
2243 | #self._compare_ok(id_, expected, given=response.body) |
|
2244 | #self._compare_ok(id_, expected, given=response.body) | |
2244 |
|
2245 | |||
2245 | def test_api_get_gists_regular_user_with_different_userid(self): |
|
2246 | def test_api_get_gists_regular_user_with_different_userid(self): | |
2246 | id_, params = _build_data(self.apikey_regular, 'get_gists', |
|
2247 | id_, params = _build_data(self.apikey_regular, 'get_gists', | |
2247 | userid=base.TEST_USER_ADMIN_LOGIN) |
|
2248 | userid=base.TEST_USER_ADMIN_LOGIN) | |
2248 | response = api_call(self, params) |
|
2249 | response = api_call(self, params) | |
2249 | expected = 'userid is not the same as your user' |
|
2250 | expected = 'userid is not the same as your user' | |
2250 | self._compare_error(id_, expected, given=response.body) |
|
2251 | self._compare_error(id_, expected, given=response.body) | |
2251 |
|
2252 | |||
2252 | def test_api_create_gist(self): |
|
2253 | def test_api_create_gist(self): | |
2253 | id_, params = _build_data(self.apikey_regular, 'create_gist', |
|
2254 | id_, params = _build_data(self.apikey_regular, 'create_gist', | |
2254 | lifetime=10, |
|
2255 | lifetime=10, | |
2255 | description='foobar-gist', |
|
2256 | description='foobar-gist', | |
2256 | gist_type='public', |
|
2257 | gist_type='public', | |
2257 | files={'foobar': {'content': 'foo'}}) |
|
2258 | files={'foobar': {'content': 'foo'}}) | |
2258 | response = api_call(self, params) |
|
2259 | response = api_call(self, params) | |
2259 | expected = { |
|
2260 | expected = { | |
2260 | 'gist': { |
|
2261 | 'gist': { | |
2261 | 'access_id': response.json['result']['gist']['access_id'], |
|
2262 | 'access_id': response.json['result']['gist']['access_id'], | |
2262 | 'created_on': response.json['result']['gist']['created_on'], |
|
2263 | 'created_on': response.json['result']['gist']['created_on'], | |
2263 | 'description': 'foobar-gist', |
|
2264 | 'description': 'foobar-gist', | |
2264 | 'expires': response.json['result']['gist']['expires'], |
|
2265 | 'expires': response.json['result']['gist']['expires'], | |
2265 | 'gist_id': response.json['result']['gist']['gist_id'], |
|
2266 | 'gist_id': response.json['result']['gist']['gist_id'], | |
2266 | 'type': 'public', |
|
2267 | 'type': 'public', | |
2267 | 'url': response.json['result']['gist']['url'] |
|
2268 | 'url': response.json['result']['gist']['url'] | |
2268 | }, |
|
2269 | }, | |
2269 | 'msg': 'created new gist' |
|
2270 | 'msg': 'created new gist' | |
2270 | } |
|
2271 | } | |
2271 | self._compare_ok(id_, expected, given=response.body) |
|
2272 | self._compare_ok(id_, expected, given=response.body) | |
2272 |
|
2273 | |||
2273 | @mock.patch.object(GistModel, 'create', raise_exception) |
|
2274 | @mock.patch.object(GistModel, 'create', raise_exception) | |
2274 | def test_api_create_gist_exception_occurred(self): |
|
2275 | def test_api_create_gist_exception_occurred(self): | |
2275 | id_, params = _build_data(self.apikey_regular, 'create_gist', |
|
2276 | id_, params = _build_data(self.apikey_regular, 'create_gist', | |
2276 | files={}) |
|
2277 | files={}) | |
2277 | response = api_call(self, params) |
|
2278 | response = api_call(self, params) | |
2278 | expected = 'failed to create gist' |
|
2279 | expected = 'failed to create gist' | |
2279 | self._compare_error(id_, expected, given=response.body) |
|
2280 | self._compare_error(id_, expected, given=response.body) | |
2280 |
|
2281 | |||
2281 | def test_api_delete_gist(self): |
|
2282 | def test_api_delete_gist(self): | |
2282 | gist_id = fixture.create_gist().gist_access_id |
|
2283 | gist_id = fixture.create_gist().gist_access_id | |
2283 | id_, params = _build_data(self.apikey, 'delete_gist', |
|
2284 | id_, params = _build_data(self.apikey, 'delete_gist', | |
2284 | gistid=gist_id) |
|
2285 | gistid=gist_id) | |
2285 | response = api_call(self, params) |
|
2286 | response = api_call(self, params) | |
2286 | expected = {'gist': None, 'msg': 'deleted gist ID:%s' % gist_id} |
|
2287 | expected = {'gist': None, 'msg': 'deleted gist ID:%s' % gist_id} | |
2287 | self._compare_ok(id_, expected, given=response.body) |
|
2288 | self._compare_ok(id_, expected, given=response.body) | |
2288 |
|
2289 | |||
2289 | def test_api_delete_gist_regular_user(self): |
|
2290 | def test_api_delete_gist_regular_user(self): | |
2290 | gist_id = fixture.create_gist(owner=self.TEST_USER_LOGIN).gist_access_id |
|
2291 | gist_id = fixture.create_gist(owner=self.TEST_USER_LOGIN).gist_access_id | |
2291 | id_, params = _build_data(self.apikey_regular, 'delete_gist', |
|
2292 | id_, params = _build_data(self.apikey_regular, 'delete_gist', | |
2292 | gistid=gist_id) |
|
2293 | gistid=gist_id) | |
2293 | response = api_call(self, params) |
|
2294 | response = api_call(self, params) | |
2294 | expected = {'gist': None, 'msg': 'deleted gist ID:%s' % gist_id} |
|
2295 | expected = {'gist': None, 'msg': 'deleted gist ID:%s' % gist_id} | |
2295 | self._compare_ok(id_, expected, given=response.body) |
|
2296 | self._compare_ok(id_, expected, given=response.body) | |
2296 |
|
2297 | |||
2297 | def test_api_delete_gist_regular_user_no_permission(self): |
|
2298 | def test_api_delete_gist_regular_user_no_permission(self): | |
2298 | gist_id = fixture.create_gist().gist_access_id |
|
2299 | gist_id = fixture.create_gist().gist_access_id | |
2299 | id_, params = _build_data(self.apikey_regular, 'delete_gist', |
|
2300 | id_, params = _build_data(self.apikey_regular, 'delete_gist', | |
2300 | gistid=gist_id) |
|
2301 | gistid=gist_id) | |
2301 | response = api_call(self, params) |
|
2302 | response = api_call(self, params) | |
2302 | expected = 'gist `%s` does not exist' % (gist_id,) |
|
2303 | expected = 'gist `%s` does not exist' % (gist_id,) | |
2303 | self._compare_error(id_, expected, given=response.body) |
|
2304 | self._compare_error(id_, expected, given=response.body) | |
2304 |
|
2305 | |||
2305 | @mock.patch.object(GistModel, 'delete', raise_exception) |
|
2306 | @mock.patch.object(GistModel, 'delete', raise_exception) | |
2306 | def test_api_delete_gist_exception_occurred(self): |
|
2307 | def test_api_delete_gist_exception_occurred(self): | |
2307 | gist_id = fixture.create_gist().gist_access_id |
|
2308 | gist_id = fixture.create_gist().gist_access_id | |
2308 | id_, params = _build_data(self.apikey, 'delete_gist', |
|
2309 | id_, params = _build_data(self.apikey, 'delete_gist', | |
2309 | gistid=gist_id) |
|
2310 | gistid=gist_id) | |
2310 | response = api_call(self, params) |
|
2311 | response = api_call(self, params) | |
2311 | expected = 'failed to delete gist ID:%s' % (gist_id,) |
|
2312 | expected = 'failed to delete gist ID:%s' % (gist_id,) | |
2312 | self._compare_error(id_, expected, given=response.body) |
|
2313 | self._compare_error(id_, expected, given=response.body) | |
2313 |
|
2314 | |||
2314 | def test_api_get_ip(self): |
|
2315 | def test_api_get_ip(self): | |
2315 | id_, params = _build_data(self.apikey, 'get_ip') |
|
2316 | id_, params = _build_data(self.apikey, 'get_ip') | |
2316 | response = api_call(self, params) |
|
2317 | response = api_call(self, params) | |
2317 | expected = { |
|
2318 | expected = { | |
2318 | 'server_ip_addr': '0.0.0.0', |
|
2319 | 'server_ip_addr': '0.0.0.0', | |
2319 | 'user_ips': [] |
|
2320 | 'user_ips': [] | |
2320 | } |
|
2321 | } | |
2321 | self._compare_ok(id_, expected, given=response.body) |
|
2322 | self._compare_ok(id_, expected, given=response.body) | |
2322 |
|
2323 | |||
2323 | def test_api_get_server_info(self): |
|
2324 | def test_api_get_server_info(self): | |
2324 | id_, params = _build_data(self.apikey, 'get_server_info') |
|
2325 | id_, params = _build_data(self.apikey, 'get_server_info') | |
2325 | response = api_call(self, params) |
|
2326 | response = api_call(self, params) | |
2326 | expected = db.Setting.get_server_info() |
|
2327 | expected = db.Setting.get_server_info() | |
2327 | self._compare_ok(id_, expected, given=response.body) |
|
2328 | self._compare_ok(id_, expected, given=response.body) | |
2328 |
|
2329 | |||
2329 | def test_api_get_changesets(self): |
|
2330 | def test_api_get_changesets(self): | |
2330 | id_, params = _build_data(self.apikey, 'get_changesets', |
|
2331 | id_, params = _build_data(self.apikey, 'get_changesets', | |
2331 | repoid=self.REPO, start=0, end=2) |
|
2332 | repoid=self.REPO, start=0, end=2) | |
2332 | response = api_call(self, params) |
|
2333 | response = api_call(self, params) | |
2333 | result = ext_json.loads(response.body)["result"] |
|
2334 | result = ext_json.loads(response.body)["result"] | |
2334 | assert len(result) == 3 |
|
2335 | assert len(result) == 3 | |
2335 | assert 'message' in result[0] |
|
2336 | assert 'message' in result[0] | |
2336 | assert 'added' not in result[0] |
|
2337 | assert 'added' not in result[0] | |
2337 |
|
2338 | |||
2338 | def test_api_get_changesets_with_max_revisions(self): |
|
2339 | def test_api_get_changesets_with_max_revisions(self): | |
2339 | id_, params = _build_data(self.apikey, 'get_changesets', |
|
2340 | id_, params = _build_data(self.apikey, 'get_changesets', | |
2340 | repoid=self.REPO, start_date="2011-02-24T00:00:00", max_revisions=10) |
|
2341 | repoid=self.REPO, start_date="2011-02-24T00:00:00", max_revisions=10) | |
2341 | response = api_call(self, params) |
|
2342 | response = api_call(self, params) | |
2342 | result = ext_json.loads(response.body)["result"] |
|
2343 | result = ext_json.loads(response.body)["result"] | |
2343 | assert len(result) == 10 |
|
2344 | assert len(result) == 10 | |
2344 | assert 'message' in result[0] |
|
2345 | assert 'message' in result[0] | |
2345 | assert 'added' not in result[0] |
|
2346 | assert 'added' not in result[0] | |
2346 |
|
2347 | |||
2347 | def test_api_get_changesets_with_branch(self): |
|
2348 | def test_api_get_changesets_with_branch(self): | |
2348 | if self.REPO == 'vcs_test_hg': |
|
2349 | if self.REPO == 'vcs_test_hg': | |
2349 | branch = 'stable' |
|
2350 | branch = 'stable' | |
2350 | else: |
|
2351 | else: | |
2351 | pytest.skip("skipping due to missing branches in git test repo") |
|
2352 | pytest.skip("skipping due to missing branches in git test repo") | |
2352 | id_, params = _build_data(self.apikey, 'get_changesets', |
|
2353 | id_, params = _build_data(self.apikey, 'get_changesets', | |
2353 | repoid=self.REPO, branch_name=branch, start_date="2011-02-24T00:00:00") |
|
2354 | repoid=self.REPO, branch_name=branch, start_date="2011-02-24T00:00:00") | |
2354 | response = api_call(self, params) |
|
2355 | response = api_call(self, params) | |
2355 | result = ext_json.loads(response.body)["result"] |
|
2356 | result = ext_json.loads(response.body)["result"] | |
2356 | assert len(result) == 5 |
|
2357 | assert len(result) == 5 | |
2357 | assert 'message' in result[0] |
|
2358 | assert 'message' in result[0] | |
2358 | assert 'added' not in result[0] |
|
2359 | assert 'added' not in result[0] | |
2359 |
|
2360 | |||
2360 | def test_api_get_changesets_with_file_list(self): |
|
2361 | def test_api_get_changesets_with_file_list(self): | |
2361 | id_, params = _build_data(self.apikey, 'get_changesets', |
|
2362 | id_, params = _build_data(self.apikey, 'get_changesets', | |
2362 | repoid=self.REPO, start_date="2010-04-07T23:30:30", end_date="2010-04-08T00:31:14", with_file_list=True) |
|
2363 | repoid=self.REPO, start_date="2010-04-07T23:30:30", end_date="2010-04-08T00:31:14", with_file_list=True) | |
2363 | response = api_call(self, params) |
|
2364 | response = api_call(self, params) | |
2364 | result = ext_json.loads(response.body)["result"] |
|
2365 | result = ext_json.loads(response.body)["result"] | |
2365 | assert len(result) == 3 |
|
2366 | assert len(result) == 3 | |
2366 | assert 'message' in result[0] |
|
2367 | assert 'message' in result[0] | |
2367 | assert 'added' in result[0] |
|
2368 | assert 'added' in result[0] | |
2368 |
|
2369 | |||
2369 | def test_api_get_changeset(self): |
|
2370 | def test_api_get_changeset(self): | |
2370 | review = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved") |
|
2371 | review = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved") | |
2371 | id_, params = _build_data(self.apikey, 'get_changeset', |
|
2372 | id_, params = _build_data(self.apikey, 'get_changeset', | |
2372 | repoid=self.REPO, raw_id=self.TEST_REVISION) |
|
2373 | repoid=self.REPO, raw_id=self.TEST_REVISION) | |
2373 | response = api_call(self, params) |
|
2374 | response = api_call(self, params) | |
2374 | result = ext_json.loads(response.body)["result"] |
|
2375 | result = ext_json.loads(response.body)["result"] | |
2375 | assert result["raw_id"] == self.TEST_REVISION |
|
2376 | assert result["raw_id"] == self.TEST_REVISION | |
2376 | assert "reviews" not in result |
|
2377 | assert "reviews" not in result | |
2377 |
|
2378 | |||
2378 | def test_api_get_changeset_with_reviews(self): |
|
2379 | def test_api_get_changeset_with_reviews(self): | |
2379 | reviewobjs = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved") |
|
2380 | reviewobjs = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved") | |
2380 | id_, params = _build_data(self.apikey, 'get_changeset', |
|
2381 | id_, params = _build_data(self.apikey, 'get_changeset', | |
2381 | repoid=self.REPO, raw_id=self.TEST_REVISION, |
|
2382 | repoid=self.REPO, raw_id=self.TEST_REVISION, | |
2382 | with_reviews=True) |
|
2383 | with_reviews=True) | |
2383 | response = api_call(self, params) |
|
2384 | response = api_call(self, params) | |
2384 | result = ext_json.loads(response.body)["result"] |
|
2385 | result = ext_json.loads(response.body)["result"] | |
2385 | assert result["raw_id"] == self.TEST_REVISION |
|
2386 | assert result["raw_id"] == self.TEST_REVISION | |
2386 | assert "reviews" in result |
|
2387 | assert "reviews" in result | |
2387 | assert len(result["reviews"]) == 1 |
|
2388 | assert len(result["reviews"]) == 1 | |
2388 | review = result["reviews"][0] |
|
2389 | review = result["reviews"][0] | |
2389 | expected = { |
|
2390 | expected = { | |
2390 | 'status': 'approved', |
|
2391 | 'status': 'approved', | |
2391 | 'modified_at': reviewobjs[0].modified_at.replace(microsecond=0).isoformat(), |
|
2392 | 'modified_at': reviewobjs[0].modified_at.replace(microsecond=0).isoformat(), | |
2392 | 'reviewer': 'test_admin', |
|
2393 | 'reviewer': 'test_admin', | |
2393 | } |
|
2394 | } | |
2394 | assert review == expected |
|
2395 | assert review == expected | |
2395 |
|
2396 | |||
2396 | def test_api_get_changeset_that_does_not_exist(self): |
|
2397 | def test_api_get_changeset_that_does_not_exist(self): | |
2397 | """ Fetch changeset status for non-existant changeset. |
|
2398 | """ Fetch changeset status for non-existant changeset. | |
2398 | revision id is the above git hash used in the test above with the |
|
2399 | revision id is the above git hash used in the test above with the | |
2399 | last 3 nibbles replaced with 0xf. Should not exist for git _or_ hg. |
|
2400 | last 3 nibbles replaced with 0xf. Should not exist for git _or_ hg. | |
2400 | """ |
|
2401 | """ | |
2401 | id_, params = _build_data(self.apikey, 'get_changeset', |
|
2402 | id_, params = _build_data(self.apikey, 'get_changeset', | |
2402 | repoid=self.REPO, raw_id = '7ab37bc680b4aa72c34d07b230c866c28e9fcfff') |
|
2403 | repoid=self.REPO, raw_id = '7ab37bc680b4aa72c34d07b230c866c28e9fcfff') | |
2403 | response = api_call(self, params) |
|
2404 | response = api_call(self, params) | |
2404 | expected = 'Changeset %s does not exist' % ('7ab37bc680b4aa72c34d07b230c866c28e9fcfff',) |
|
2405 | expected = 'Changeset %s does not exist' % ('7ab37bc680b4aa72c34d07b230c866c28e9fcfff',) | |
2405 | self._compare_error(id_, expected, given=response.body) |
|
2406 | self._compare_error(id_, expected, given=response.body) | |
2406 |
|
2407 | |||
2407 | def test_api_get_changeset_without_permission(self): |
|
2408 | def test_api_get_changeset_without_permission(self): | |
2408 | review = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved") |
|
2409 | review = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved") | |
2409 | RepoModel().revoke_user_permission(repo=self.REPO, user=self.TEST_USER_LOGIN) |
|
2410 | RepoModel().revoke_user_permission(repo=self.REPO, user=self.TEST_USER_LOGIN) | |
2410 | RepoModel().revoke_user_permission(repo=self.REPO, user="default") |
|
2411 | RepoModel().revoke_user_permission(repo=self.REPO, user="default") | |
2411 | id_, params = _build_data(self.apikey_regular, 'get_changeset', |
|
2412 | id_, params = _build_data(self.apikey_regular, 'get_changeset', | |
2412 | repoid=self.REPO, raw_id=self.TEST_REVISION) |
|
2413 | repoid=self.REPO, raw_id=self.TEST_REVISION) | |
2413 | response = api_call(self, params) |
|
2414 | response = api_call(self, params) | |
2414 | expected = 'Access denied to repo %s' % self.REPO |
|
2415 | expected = 'Access denied to repo %s' % self.REPO | |
2415 | self._compare_error(id_, expected, given=response.body) |
|
2416 | self._compare_error(id_, expected, given=response.body) | |
2416 |
|
2417 | |||
2417 | def test_api_get_pullrequest(self): |
|
2418 | def test_api_get_pullrequest(self): | |
2418 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'get test') |
|
2419 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'get test') | |
2419 | random_id = random.randrange(1, 9999) |
|
2420 | random_id = random.randrange(1, 9999) | |
2420 | params = ascii_bytes(ext_json.dumps({ |
|
2421 | params = ascii_bytes(ext_json.dumps({ | |
2421 | "id": random_id, |
|
2422 | "id": random_id, | |
2422 | "api_key": self.apikey, |
|
2423 | "api_key": self.apikey, | |
2423 | "method": 'get_pullrequest', |
|
2424 | "method": 'get_pullrequest', | |
2424 | "args": {"pullrequest_id": pull_request_id}, |
|
2425 | "args": {"pullrequest_id": pull_request_id}, | |
2425 | })) |
|
2426 | })) | |
2426 | response = api_call(self, params) |
|
2427 | response = api_call(self, params) | |
2427 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2428 | pullrequest = db.PullRequest().get(pull_request_id) | |
2428 | expected = { |
|
2429 | expected = { | |
2429 | "status": "new", |
|
2430 | "status": "new", | |
2430 | "pull_request_id": pull_request_id, |
|
2431 | "pull_request_id": pull_request_id, | |
2431 | "description": "No description", |
|
2432 | "description": "No description", | |
2432 | "url": "/%s/pull-request/%s/_/%s" % (self.REPO, pull_request_id, "stable"), |
|
2433 | "url": "/%s/pull-request/%s/_/%s" % (self.REPO, pull_request_id, "stable"), | |
2433 | "reviewers": [{"username": "test_regular"}], |
|
2434 | "reviewers": [{"username": "test_regular"}], | |
2434 | "org_repo_url": "http://localhost:80/%s" % self.REPO, |
|
2435 | "org_repo_url": "http://localhost:80/%s" % self.REPO, | |
2435 | "org_ref_parts": ["branch", "stable", self.TEST_PR_SRC], |
|
2436 | "org_ref_parts": ["branch", "stable", self.TEST_PR_SRC], | |
2436 | "other_ref_parts": ["branch", "default", self.TEST_PR_DST], |
|
2437 | "other_ref_parts": ["branch", "default", self.TEST_PR_DST], | |
2437 | "comments": [{"username": base.TEST_USER_ADMIN_LOGIN, "text": "", |
|
2438 | "comments": [{"username": base.TEST_USER_ADMIN_LOGIN, "text": "", | |
2438 | "comment_id": pullrequest.comments[0].comment_id}], |
|
2439 | "comment_id": pullrequest.comments[0].comment_id}], | |
2439 | "owner": base.TEST_USER_ADMIN_LOGIN, |
|
2440 | "owner": base.TEST_USER_ADMIN_LOGIN, | |
2440 | "statuses": [{"status": "under_review", "reviewer": base.TEST_USER_ADMIN_LOGIN, "modified_at": "2000-01-01T00:00:00"} for i in range(0, len(self.TEST_PR_REVISIONS))], |
|
2441 | "statuses": [{"status": "under_review", "reviewer": base.TEST_USER_ADMIN_LOGIN, "modified_at": "2000-01-01T00:00:00"} for i in range(0, len(self.TEST_PR_REVISIONS))], | |
2441 | "title": "get test", |
|
2442 | "title": "get test", | |
2442 | "revisions": self.TEST_PR_REVISIONS, |
|
2443 | "revisions": self.TEST_PR_REVISIONS, | |
2443 | "created_on": "2000-01-01T00:00:00", |
|
2444 | "created_on": "2000-01-01T00:00:00", | |
2444 | "updated_on": "2000-01-01T00:00:00", |
|
2445 | "updated_on": "2000-01-01T00:00:00", | |
2445 | } |
|
2446 | } | |
2446 | self._compare_ok(random_id, expected, |
|
2447 | self._compare_ok(random_id, expected, | |
2447 | given=re.sub(br"\d\d\d\d\-\d\d\-\d\dT\d\d\:\d\d\:\d\d", |
|
2448 | given=re.sub(br"\d\d\d\d\-\d\d\-\d\dT\d\d\:\d\d\:\d\d", | |
2448 | b"2000-01-01T00:00:00", response.body)) |
|
2449 | b"2000-01-01T00:00:00", response.body)) | |
2449 |
|
2450 | |||
2450 | def test_api_close_pullrequest(self): |
|
2451 | def test_api_close_pullrequest(self): | |
2451 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'close test') |
|
2452 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'close test') | |
2452 | random_id = random.randrange(1, 9999) |
|
2453 | random_id = random.randrange(1, 9999) | |
2453 | params = ascii_bytes(ext_json.dumps({ |
|
2454 | params = ascii_bytes(ext_json.dumps({ | |
2454 | "id": random_id, |
|
2455 | "id": random_id, | |
2455 | "api_key": self.apikey, |
|
2456 | "api_key": self.apikey, | |
2456 | "method": "comment_pullrequest", |
|
2457 | "method": "comment_pullrequest", | |
2457 | "args": {"pull_request_id": pull_request_id, "close_pr": True}, |
|
2458 | "args": {"pull_request_id": pull_request_id, "close_pr": True}, | |
2458 | })) |
|
2459 | })) | |
2459 | response = api_call(self, params) |
|
2460 | response = api_call(self, params) | |
2460 | self._compare_ok(random_id, True, given=response.body) |
|
2461 | self._compare_ok(random_id, True, given=response.body) | |
2461 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2462 | pullrequest = db.PullRequest().get(pull_request_id) | |
2462 | assert pullrequest.comments[-1].text == '' |
|
2463 | assert pullrequest.comments[-1].text == '' | |
2463 | assert pullrequest.status == db.PullRequest.STATUS_CLOSED |
|
2464 | assert pullrequest.status == db.PullRequest.STATUS_CLOSED | |
2464 | assert pullrequest.is_closed() == True |
|
2465 | assert pullrequest.is_closed() == True | |
2465 |
|
2466 | |||
2466 | def test_api_status_pullrequest(self): |
|
2467 | def test_api_status_pullrequest(self): | |
2467 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, "status test") |
|
2468 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, "status test") | |
2468 |
|
2469 | |||
2469 | random_id = random.randrange(1, 9999) |
|
2470 | random_id = random.randrange(1, 9999) | |
2470 | params = ascii_bytes(ext_json.dumps({ |
|
2471 | params = ascii_bytes(ext_json.dumps({ | |
2471 | "id": random_id, |
|
2472 | "id": random_id, | |
2472 | "api_key": db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN).api_key, |
|
2473 | "api_key": db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN).api_key, | |
2473 | "method": "comment_pullrequest", |
|
2474 | "method": "comment_pullrequest", | |
2474 | "args": {"pull_request_id": pull_request_id, "status": db.ChangesetStatus.STATUS_APPROVED}, |
|
2475 | "args": {"pull_request_id": pull_request_id, "status": db.ChangesetStatus.STATUS_APPROVED}, | |
2475 | })) |
|
2476 | })) | |
2476 | response = api_call(self, params) |
|
2477 | response = api_call(self, params) | |
2477 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2478 | pullrequest = db.PullRequest().get(pull_request_id) | |
2478 | self._compare_error(random_id, "No permission to change pull request status. User needs to be admin, owner or reviewer.", given=response.body) |
|
2479 | self._compare_error(random_id, "No permission to change pull request status. User needs to be admin, owner or reviewer.", given=response.body) | |
2479 | assert db.ChangesetStatus.STATUS_UNDER_REVIEW == ChangesetStatusModel().calculate_pull_request_result(pullrequest)[2] |
|
2480 | assert db.ChangesetStatus.STATUS_UNDER_REVIEW == ChangesetStatusModel().calculate_pull_request_result(pullrequest)[2] | |
2480 | params = ascii_bytes(ext_json.dumps({ |
|
2481 | params = ascii_bytes(ext_json.dumps({ | |
2481 | "id": random_id, |
|
2482 | "id": random_id, | |
2482 | "api_key": db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN).api_key, |
|
2483 | "api_key": db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN).api_key, | |
2483 | "method": "comment_pullrequest", |
|
2484 | "method": "comment_pullrequest", | |
2484 | "args": {"pull_request_id": pull_request_id, "status": db.ChangesetStatus.STATUS_APPROVED}, |
|
2485 | "args": {"pull_request_id": pull_request_id, "status": db.ChangesetStatus.STATUS_APPROVED}, | |
2485 | })) |
|
2486 | })) | |
2486 | response = api_call(self, params) |
|
2487 | response = api_call(self, params) | |
2487 | self._compare_ok(random_id, True, given=response.body) |
|
2488 | self._compare_ok(random_id, True, given=response.body) | |
2488 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2489 | pullrequest = db.PullRequest().get(pull_request_id) | |
2489 | assert db.ChangesetStatus.STATUS_APPROVED == ChangesetStatusModel().calculate_pull_request_result(pullrequest)[2] |
|
2490 | assert db.ChangesetStatus.STATUS_APPROVED == ChangesetStatusModel().calculate_pull_request_result(pullrequest)[2] | |
2490 |
|
2491 | |||
2491 | def test_api_comment_pullrequest(self): |
|
2492 | def test_api_comment_pullrequest(self): | |
2492 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, "comment test") |
|
2493 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, "comment test") | |
2493 | random_id = random.randrange(1, 9999) |
|
2494 | random_id = random.randrange(1, 9999) | |
2494 | params = ascii_bytes(ext_json.dumps({ |
|
2495 | params = ascii_bytes(ext_json.dumps({ | |
2495 | "id": random_id, |
|
2496 | "id": random_id, | |
2496 | "api_key": self.apikey, |
|
2497 | "api_key": self.apikey, | |
2497 | "method": "comment_pullrequest", |
|
2498 | "method": "comment_pullrequest", | |
2498 | "args": {"pull_request_id": pull_request_id, "comment_msg": "Looks good to me"}, |
|
2499 | "args": {"pull_request_id": pull_request_id, "comment_msg": "Looks good to me"}, | |
2499 | })) |
|
2500 | })) | |
2500 | response = api_call(self, params) |
|
2501 | response = api_call(self, params) | |
2501 | self._compare_ok(random_id, True, given=response.body) |
|
2502 | self._compare_ok(random_id, True, given=response.body) | |
2502 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2503 | pullrequest = db.PullRequest().get(pull_request_id) | |
2503 | assert pullrequest.comments[-1].text == 'Looks good to me' |
|
2504 | assert pullrequest.comments[-1].text == 'Looks good to me' | |
2504 |
|
2505 | |||
2505 | def test_api_edit_reviewers_add_single(self): |
|
2506 | def test_api_edit_reviewers_add_single(self): | |
2506 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2507 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2507 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2508 | pullrequest = db.PullRequest().get(pull_request_id) | |
2508 | pullrequest.owner = self.test_user |
|
2509 | pullrequest.owner = self.test_user | |
2509 | random_id = random.randrange(1, 9999) |
|
2510 | random_id = random.randrange(1, 9999) | |
2510 | params = ascii_bytes(ext_json.dumps({ |
|
2511 | params = ascii_bytes(ext_json.dumps({ | |
2511 | "id": random_id, |
|
2512 | "id": random_id, | |
2512 | "api_key": self.apikey_regular, |
|
2513 | "api_key": self.apikey_regular, | |
2513 | "method": "edit_reviewers", |
|
2514 | "method": "edit_reviewers", | |
2514 | "args": {"pull_request_id": pull_request_id, "add": base.TEST_USER_REGULAR2_LOGIN}, |
|
2515 | "args": {"pull_request_id": pull_request_id, "add": base.TEST_USER_REGULAR2_LOGIN}, | |
2515 | })) |
|
2516 | })) | |
2516 | response = api_call(self, params) |
|
2517 | response = api_call(self, params) | |
2517 | expected = { 'added': [base.TEST_USER_REGULAR2_LOGIN], 'already_present': [], 'removed': [] } |
|
2518 | expected = { 'added': [base.TEST_USER_REGULAR2_LOGIN], 'already_present': [], 'removed': [] } | |
2518 |
|
2519 | |||
2519 | self._compare_ok(random_id, expected, given=response.body) |
|
2520 | self._compare_ok(random_id, expected, given=response.body) | |
2520 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) in pullrequest.get_reviewer_users() |
|
2521 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) in pullrequest.get_reviewer_users() | |
2521 |
|
2522 | |||
2522 | def test_api_edit_reviewers_add_nonexistent(self): |
|
2523 | def test_api_edit_reviewers_add_nonexistent(self): | |
2523 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2524 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2524 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2525 | pullrequest = db.PullRequest().get(pull_request_id) | |
2525 | pullrequest.owner = self.test_user |
|
2526 | pullrequest.owner = self.test_user | |
2526 | random_id = random.randrange(1, 9999) |
|
2527 | random_id = random.randrange(1, 9999) | |
2527 | params = ascii_bytes(ext_json.dumps({ |
|
2528 | params = ascii_bytes(ext_json.dumps({ | |
2528 | "id": random_id, |
|
2529 | "id": random_id, | |
2529 | "api_key": self.apikey_regular, |
|
2530 | "api_key": self.apikey_regular, | |
2530 | "method": "edit_reviewers", |
|
2531 | "method": "edit_reviewers", | |
2531 | "args": {"pull_request_id": pull_request_id, "add": 999}, |
|
2532 | "args": {"pull_request_id": pull_request_id, "add": 999}, | |
2532 | })) |
|
2533 | })) | |
2533 | response = api_call(self, params) |
|
2534 | response = api_call(self, params) | |
2534 |
|
2535 | |||
2535 | self._compare_error(random_id, "user `999` does not exist", given=response.body) |
|
2536 | self._compare_error(random_id, "user `999` does not exist", given=response.body) | |
2536 |
|
2537 | |||
2537 | def test_api_edit_reviewers_add_multiple(self): |
|
2538 | def test_api_edit_reviewers_add_multiple(self): | |
2538 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2539 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2539 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2540 | pullrequest = db.PullRequest().get(pull_request_id) | |
2540 | pullrequest.owner = self.test_user |
|
2541 | pullrequest.owner = self.test_user | |
2541 | random_id = random.randrange(1, 9999) |
|
2542 | random_id = random.randrange(1, 9999) | |
2542 | params = ascii_bytes(ext_json.dumps({ |
|
2543 | params = ascii_bytes(ext_json.dumps({ | |
2543 | "id": random_id, |
|
2544 | "id": random_id, | |
2544 | "api_key": self.apikey_regular, |
|
2545 | "api_key": self.apikey_regular, | |
2545 | "method": "edit_reviewers", |
|
2546 | "method": "edit_reviewers", | |
2546 | "args": { |
|
2547 | "args": { | |
2547 | "pull_request_id": pull_request_id, |
|
2548 | "pull_request_id": pull_request_id, | |
2548 | "add": [ self.TEST_USER_LOGIN, base.TEST_USER_REGULAR2_LOGIN ] |
|
2549 | "add": [ self.TEST_USER_LOGIN, base.TEST_USER_REGULAR2_LOGIN ] | |
2549 | }, |
|
2550 | }, | |
2550 | })) |
|
2551 | })) | |
2551 | response = api_call(self, params) |
|
2552 | response = api_call(self, params) | |
2552 | # list order depends on python sorting hash, which is randomized |
|
2553 | # list order depends on python sorting hash, which is randomized | |
2553 | assert set(ext_json.loads(response.body)['result']['added']) == set([base.TEST_USER_REGULAR2_LOGIN, self.TEST_USER_LOGIN]) |
|
2554 | assert set(ext_json.loads(response.body)['result']['added']) == set([base.TEST_USER_REGULAR2_LOGIN, self.TEST_USER_LOGIN]) | |
2554 | assert set(ext_json.loads(response.body)['result']['already_present']) == set() |
|
2555 | assert set(ext_json.loads(response.body)['result']['already_present']) == set() | |
2555 | assert set(ext_json.loads(response.body)['result']['removed']) == set() |
|
2556 | assert set(ext_json.loads(response.body)['result']['removed']) == set() | |
2556 |
|
2557 | |||
2557 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) in pullrequest.get_reviewer_users() |
|
2558 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) in pullrequest.get_reviewer_users() | |
2558 | assert db.User.get_by_username(self.TEST_USER_LOGIN) in pullrequest.get_reviewer_users() |
|
2559 | assert db.User.get_by_username(self.TEST_USER_LOGIN) in pullrequest.get_reviewer_users() | |
2559 |
|
2560 | |||
2560 | def test_api_edit_reviewers_add_already_present(self): |
|
2561 | def test_api_edit_reviewers_add_already_present(self): | |
2561 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2562 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2562 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2563 | pullrequest = db.PullRequest().get(pull_request_id) | |
2563 | pullrequest.owner = self.test_user |
|
2564 | pullrequest.owner = self.test_user | |
2564 | random_id = random.randrange(1, 9999) |
|
2565 | random_id = random.randrange(1, 9999) | |
2565 | params = ascii_bytes(ext_json.dumps({ |
|
2566 | params = ascii_bytes(ext_json.dumps({ | |
2566 | "id": random_id, |
|
2567 | "id": random_id, | |
2567 | "api_key": self.apikey_regular, |
|
2568 | "api_key": self.apikey_regular, | |
2568 | "method": "edit_reviewers", |
|
2569 | "method": "edit_reviewers", | |
2569 | "args": { |
|
2570 | "args": { | |
2570 | "pull_request_id": pull_request_id, |
|
2571 | "pull_request_id": pull_request_id, | |
2571 | "add": [ base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_REGULAR2_LOGIN ] |
|
2572 | "add": [ base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_REGULAR2_LOGIN ] | |
2572 | }, |
|
2573 | }, | |
2573 | })) |
|
2574 | })) | |
2574 | response = api_call(self, params) |
|
2575 | response = api_call(self, params) | |
2575 | expected = { 'added': [base.TEST_USER_REGULAR2_LOGIN], |
|
2576 | expected = { 'added': [base.TEST_USER_REGULAR2_LOGIN], | |
2576 | 'already_present': [base.TEST_USER_REGULAR_LOGIN], |
|
2577 | 'already_present': [base.TEST_USER_REGULAR_LOGIN], | |
2577 | 'removed': [], |
|
2578 | 'removed': [], | |
2578 | } |
|
2579 | } | |
2579 |
|
2580 | |||
2580 | self._compare_ok(random_id, expected, given=response.body) |
|
2581 | self._compare_ok(random_id, expected, given=response.body) | |
2581 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2582 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2582 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) in pullrequest.get_reviewer_users() |
|
2583 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) in pullrequest.get_reviewer_users() | |
2583 |
|
2584 | |||
2584 | def test_api_edit_reviewers_add_closed(self): |
|
2585 | def test_api_edit_reviewers_add_closed(self): | |
2585 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2586 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2586 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2587 | pullrequest = db.PullRequest().get(pull_request_id) | |
2587 | pullrequest.owner = self.test_user |
|
2588 | pullrequest.owner = self.test_user | |
2588 | PullRequestModel().close_pull_request(pull_request_id) |
|
2589 | PullRequestModel().close_pull_request(pull_request_id) | |
2589 | random_id = random.randrange(1, 9999) |
|
2590 | random_id = random.randrange(1, 9999) | |
2590 | params = ascii_bytes(ext_json.dumps({ |
|
2591 | params = ascii_bytes(ext_json.dumps({ | |
2591 | "id": random_id, |
|
2592 | "id": random_id, | |
2592 | "api_key": self.apikey_regular, |
|
2593 | "api_key": self.apikey_regular, | |
2593 | "method": "edit_reviewers", |
|
2594 | "method": "edit_reviewers", | |
2594 | "args": {"pull_request_id": pull_request_id, "add": base.TEST_USER_REGULAR2_LOGIN}, |
|
2595 | "args": {"pull_request_id": pull_request_id, "add": base.TEST_USER_REGULAR2_LOGIN}, | |
2595 | })) |
|
2596 | })) | |
2596 | response = api_call(self, params) |
|
2597 | response = api_call(self, params) | |
2597 | self._compare_error(random_id, "Cannot edit reviewers of a closed pull request.", given=response.body) |
|
2598 | self._compare_error(random_id, "Cannot edit reviewers of a closed pull request.", given=response.body) | |
2598 |
|
2599 | |||
2599 | def test_api_edit_reviewers_add_not_owner(self): |
|
2600 | def test_api_edit_reviewers_add_not_owner(self): | |
2600 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2601 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2601 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2602 | pullrequest = db.PullRequest().get(pull_request_id) | |
2602 | pullrequest.owner = db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) |
|
2603 | pullrequest.owner = db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) | |
2603 | random_id = random.randrange(1, 9999) |
|
2604 | random_id = random.randrange(1, 9999) | |
2604 | params = ascii_bytes(ext_json.dumps({ |
|
2605 | params = ascii_bytes(ext_json.dumps({ | |
2605 | "id": random_id, |
|
2606 | "id": random_id, | |
2606 | "api_key": self.apikey_regular, |
|
2607 | "api_key": self.apikey_regular, | |
2607 | "method": "edit_reviewers", |
|
2608 | "method": "edit_reviewers", | |
2608 | "args": {"pull_request_id": pull_request_id, "add": base.TEST_USER_REGULAR2_LOGIN}, |
|
2609 | "args": {"pull_request_id": pull_request_id, "add": base.TEST_USER_REGULAR2_LOGIN}, | |
2609 | })) |
|
2610 | })) | |
2610 | response = api_call(self, params) |
|
2611 | response = api_call(self, params) | |
2611 | self._compare_error(random_id, "No permission to edit reviewers of this pull request. User needs to be admin or pull request owner.", given=response.body) |
|
2612 | self._compare_error(random_id, "No permission to edit reviewers of this pull request. User needs to be admin or pull request owner.", given=response.body) | |
2612 |
|
2613 | |||
2613 |
|
2614 | |||
2614 | def test_api_edit_reviewers_remove_single(self): |
|
2615 | def test_api_edit_reviewers_remove_single(self): | |
2615 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2616 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2616 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2617 | pullrequest = db.PullRequest().get(pull_request_id) | |
2617 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2618 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2618 |
|
2619 | |||
2619 | pullrequest.owner = self.test_user |
|
2620 | pullrequest.owner = self.test_user | |
2620 | random_id = random.randrange(1, 9999) |
|
2621 | random_id = random.randrange(1, 9999) | |
2621 | params = ascii_bytes(ext_json.dumps({ |
|
2622 | params = ascii_bytes(ext_json.dumps({ | |
2622 | "id": random_id, |
|
2623 | "id": random_id, | |
2623 | "api_key": self.apikey_regular, |
|
2624 | "api_key": self.apikey_regular, | |
2624 | "method": "edit_reviewers", |
|
2625 | "method": "edit_reviewers", | |
2625 | "args": {"pull_request_id": pull_request_id, "remove": base.TEST_USER_REGULAR_LOGIN}, |
|
2626 | "args": {"pull_request_id": pull_request_id, "remove": base.TEST_USER_REGULAR_LOGIN}, | |
2626 | })) |
|
2627 | })) | |
2627 | response = api_call(self, params) |
|
2628 | response = api_call(self, params) | |
2628 |
|
2629 | |||
2629 | expected = { 'added': [], |
|
2630 | expected = { 'added': [], | |
2630 | 'already_present': [], |
|
2631 | 'already_present': [], | |
2631 | 'removed': [base.TEST_USER_REGULAR_LOGIN], |
|
2632 | 'removed': [base.TEST_USER_REGULAR_LOGIN], | |
2632 | } |
|
2633 | } | |
2633 | self._compare_ok(random_id, expected, given=response.body) |
|
2634 | self._compare_ok(random_id, expected, given=response.body) | |
2634 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) not in pullrequest.get_reviewer_users() |
|
2635 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) not in pullrequest.get_reviewer_users() | |
2635 |
|
2636 | |||
2636 | def test_api_edit_reviewers_remove_nonexistent(self): |
|
2637 | def test_api_edit_reviewers_remove_nonexistent(self): | |
2637 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2638 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2638 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2639 | pullrequest = db.PullRequest().get(pull_request_id) | |
2639 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2640 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2640 |
|
2641 | |||
2641 | pullrequest.owner = self.test_user |
|
2642 | pullrequest.owner = self.test_user | |
2642 | random_id = random.randrange(1, 9999) |
|
2643 | random_id = random.randrange(1, 9999) | |
2643 | params = ascii_bytes(ext_json.dumps({ |
|
2644 | params = ascii_bytes(ext_json.dumps({ | |
2644 | "id": random_id, |
|
2645 | "id": random_id, | |
2645 | "api_key": self.apikey_regular, |
|
2646 | "api_key": self.apikey_regular, | |
2646 | "method": "edit_reviewers", |
|
2647 | "method": "edit_reviewers", | |
2647 | "args": {"pull_request_id": pull_request_id, "remove": 999}, |
|
2648 | "args": {"pull_request_id": pull_request_id, "remove": 999}, | |
2648 | })) |
|
2649 | })) | |
2649 | response = api_call(self, params) |
|
2650 | response = api_call(self, params) | |
2650 |
|
2651 | |||
2651 | self._compare_error(random_id, "user `999` does not exist", given=response.body) |
|
2652 | self._compare_error(random_id, "user `999` does not exist", given=response.body) | |
2652 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2653 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2653 |
|
2654 | |||
2654 | def test_api_edit_reviewers_remove_nonpresent(self): |
|
2655 | def test_api_edit_reviewers_remove_nonpresent(self): | |
2655 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2656 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2656 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2657 | pullrequest = db.PullRequest().get(pull_request_id) | |
2657 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2658 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2658 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) not in pullrequest.get_reviewer_users() |
|
2659 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) not in pullrequest.get_reviewer_users() | |
2659 |
|
2660 | |||
2660 | pullrequest.owner = self.test_user |
|
2661 | pullrequest.owner = self.test_user | |
2661 | random_id = random.randrange(1, 9999) |
|
2662 | random_id = random.randrange(1, 9999) | |
2662 | params = ascii_bytes(ext_json.dumps({ |
|
2663 | params = ascii_bytes(ext_json.dumps({ | |
2663 | "id": random_id, |
|
2664 | "id": random_id, | |
2664 | "api_key": self.apikey_regular, |
|
2665 | "api_key": self.apikey_regular, | |
2665 | "method": "edit_reviewers", |
|
2666 | "method": "edit_reviewers", | |
2666 | "args": {"pull_request_id": pull_request_id, "remove": base.TEST_USER_REGULAR2_LOGIN}, |
|
2667 | "args": {"pull_request_id": pull_request_id, "remove": base.TEST_USER_REGULAR2_LOGIN}, | |
2667 | })) |
|
2668 | })) | |
2668 | response = api_call(self, params) |
|
2669 | response = api_call(self, params) | |
2669 |
|
2670 | |||
2670 | # NOTE: no explicit indication that removed user was not even a reviewer |
|
2671 | # NOTE: no explicit indication that removed user was not even a reviewer | |
2671 | expected = { 'added': [], |
|
2672 | expected = { 'added': [], | |
2672 | 'already_present': [], |
|
2673 | 'already_present': [], | |
2673 | 'removed': [base.TEST_USER_REGULAR2_LOGIN], |
|
2674 | 'removed': [base.TEST_USER_REGULAR2_LOGIN], | |
2674 | } |
|
2675 | } | |
2675 | self._compare_ok(random_id, expected, given=response.body) |
|
2676 | self._compare_ok(random_id, expected, given=response.body) | |
2676 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2677 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2677 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) not in pullrequest.get_reviewer_users() |
|
2678 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) not in pullrequest.get_reviewer_users() | |
2678 |
|
2679 | |||
2679 | def test_api_edit_reviewers_remove_multiple(self): |
|
2680 | def test_api_edit_reviewers_remove_multiple(self): | |
2680 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2681 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2681 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2682 | pullrequest = db.PullRequest().get(pull_request_id) | |
2682 | prr = db.PullRequestReviewer(db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN), pullrequest) |
|
2683 | prr = db.PullRequestReviewer(db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN), pullrequest) | |
2683 | meta.Session().add(prr) |
|
2684 | meta.Session().add(prr) | |
2684 | meta.Session().commit() |
|
2685 | meta.Session().commit() | |
2685 |
|
2686 | |||
2686 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2687 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2687 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) in pullrequest.get_reviewer_users() |
|
2688 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) in pullrequest.get_reviewer_users() | |
2688 |
|
2689 | |||
2689 | pullrequest.owner = self.test_user |
|
2690 | pullrequest.owner = self.test_user | |
2690 | random_id = random.randrange(1, 9999) |
|
2691 | random_id = random.randrange(1, 9999) | |
2691 | params = ascii_bytes(ext_json.dumps({ |
|
2692 | params = ascii_bytes(ext_json.dumps({ | |
2692 | "id": random_id, |
|
2693 | "id": random_id, | |
2693 | "api_key": self.apikey_regular, |
|
2694 | "api_key": self.apikey_regular, | |
2694 | "method": "edit_reviewers", |
|
2695 | "method": "edit_reviewers", | |
2695 | "args": {"pull_request_id": pull_request_id, "remove": [ base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_REGULAR2_LOGIN ] }, |
|
2696 | "args": {"pull_request_id": pull_request_id, "remove": [ base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_REGULAR2_LOGIN ] }, | |
2696 | })) |
|
2697 | })) | |
2697 | response = api_call(self, params) |
|
2698 | response = api_call(self, params) | |
2698 |
|
2699 | |||
2699 | # list order depends on python sorting hash, which is randomized |
|
2700 | # list order depends on python sorting hash, which is randomized | |
2700 | assert set(ext_json.loads(response.body)['result']['added']) == set() |
|
2701 | assert set(ext_json.loads(response.body)['result']['added']) == set() | |
2701 | assert set(ext_json.loads(response.body)['result']['already_present']) == set() |
|
2702 | assert set(ext_json.loads(response.body)['result']['already_present']) == set() | |
2702 | assert set(ext_json.loads(response.body)['result']['removed']) == set([base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_REGULAR2_LOGIN]) |
|
2703 | assert set(ext_json.loads(response.body)['result']['removed']) == set([base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_REGULAR2_LOGIN]) | |
2703 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) not in pullrequest.get_reviewer_users() |
|
2704 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) not in pullrequest.get_reviewer_users() | |
2704 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) not in pullrequest.get_reviewer_users() |
|
2705 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) not in pullrequest.get_reviewer_users() | |
2705 |
|
2706 | |||
2706 | def test_api_edit_reviewers_remove_closed(self): |
|
2707 | def test_api_edit_reviewers_remove_closed(self): | |
2707 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2708 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2708 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2709 | pullrequest = db.PullRequest().get(pull_request_id) | |
2709 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2710 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2710 | PullRequestModel().close_pull_request(pull_request_id) |
|
2711 | PullRequestModel().close_pull_request(pull_request_id) | |
2711 |
|
2712 | |||
2712 | pullrequest.owner = self.test_user |
|
2713 | pullrequest.owner = self.test_user | |
2713 | random_id = random.randrange(1, 9999) |
|
2714 | random_id = random.randrange(1, 9999) | |
2714 | params = ascii_bytes(ext_json.dumps({ |
|
2715 | params = ascii_bytes(ext_json.dumps({ | |
2715 | "id": random_id, |
|
2716 | "id": random_id, | |
2716 | "api_key": self.apikey_regular, |
|
2717 | "api_key": self.apikey_regular, | |
2717 | "method": "edit_reviewers", |
|
2718 | "method": "edit_reviewers", | |
2718 | "args": {"pull_request_id": pull_request_id, "remove": base.TEST_USER_REGULAR_LOGIN}, |
|
2719 | "args": {"pull_request_id": pull_request_id, "remove": base.TEST_USER_REGULAR_LOGIN}, | |
2719 | })) |
|
2720 | })) | |
2720 | response = api_call(self, params) |
|
2721 | response = api_call(self, params) | |
2721 |
|
2722 | |||
2722 | self._compare_error(random_id, "Cannot edit reviewers of a closed pull request.", given=response.body) |
|
2723 | self._compare_error(random_id, "Cannot edit reviewers of a closed pull request.", given=response.body) | |
2723 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2724 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2724 |
|
2725 | |||
2725 | def test_api_edit_reviewers_remove_not_owner(self): |
|
2726 | def test_api_edit_reviewers_remove_not_owner(self): | |
2726 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2727 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2727 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2728 | pullrequest = db.PullRequest().get(pull_request_id) | |
2728 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2729 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2729 |
|
2730 | |||
2730 | pullrequest.owner = db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) |
|
2731 | pullrequest.owner = db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) | |
2731 | random_id = random.randrange(1, 9999) |
|
2732 | random_id = random.randrange(1, 9999) | |
2732 | params = ascii_bytes(ext_json.dumps({ |
|
2733 | params = ascii_bytes(ext_json.dumps({ | |
2733 | "id": random_id, |
|
2734 | "id": random_id, | |
2734 | "api_key": self.apikey_regular, |
|
2735 | "api_key": self.apikey_regular, | |
2735 | "method": "edit_reviewers", |
|
2736 | "method": "edit_reviewers", | |
2736 | "args": {"pull_request_id": pull_request_id, "remove": base.TEST_USER_REGULAR_LOGIN}, |
|
2737 | "args": {"pull_request_id": pull_request_id, "remove": base.TEST_USER_REGULAR_LOGIN}, | |
2737 | })) |
|
2738 | })) | |
2738 | response = api_call(self, params) |
|
2739 | response = api_call(self, params) | |
2739 |
|
2740 | |||
2740 | self._compare_error(random_id, "No permission to edit reviewers of this pull request. User needs to be admin or pull request owner.", given=response.body) |
|
2741 | self._compare_error(random_id, "No permission to edit reviewers of this pull request. User needs to be admin or pull request owner.", given=response.body) | |
2741 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2742 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2742 |
|
2743 | |||
2743 | def test_api_edit_reviewers_add_remove_single(self): |
|
2744 | def test_api_edit_reviewers_add_remove_single(self): | |
2744 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2745 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2745 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2746 | pullrequest = db.PullRequest().get(pull_request_id) | |
2746 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2747 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2747 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) not in pullrequest.get_reviewer_users() |
|
2748 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) not in pullrequest.get_reviewer_users() | |
2748 |
|
2749 | |||
2749 | pullrequest.owner = self.test_user |
|
2750 | pullrequest.owner = self.test_user | |
2750 | random_id = random.randrange(1, 9999) |
|
2751 | random_id = random.randrange(1, 9999) | |
2751 | params = ascii_bytes(ext_json.dumps({ |
|
2752 | params = ascii_bytes(ext_json.dumps({ | |
2752 | "id": random_id, |
|
2753 | "id": random_id, | |
2753 | "api_key": self.apikey_regular, |
|
2754 | "api_key": self.apikey_regular, | |
2754 | "method": "edit_reviewers", |
|
2755 | "method": "edit_reviewers", | |
2755 | "args": {"pull_request_id": pull_request_id, |
|
2756 | "args": {"pull_request_id": pull_request_id, | |
2756 | "add": base.TEST_USER_REGULAR2_LOGIN, |
|
2757 | "add": base.TEST_USER_REGULAR2_LOGIN, | |
2757 | "remove": base.TEST_USER_REGULAR_LOGIN |
|
2758 | "remove": base.TEST_USER_REGULAR_LOGIN | |
2758 | }, |
|
2759 | }, | |
2759 | })) |
|
2760 | })) | |
2760 | response = api_call(self, params) |
|
2761 | response = api_call(self, params) | |
2761 |
|
2762 | |||
2762 | expected = { 'added': [base.TEST_USER_REGULAR2_LOGIN], |
|
2763 | expected = { 'added': [base.TEST_USER_REGULAR2_LOGIN], | |
2763 | 'already_present': [], |
|
2764 | 'already_present': [], | |
2764 | 'removed': [base.TEST_USER_REGULAR_LOGIN], |
|
2765 | 'removed': [base.TEST_USER_REGULAR_LOGIN], | |
2765 | } |
|
2766 | } | |
2766 | self._compare_ok(random_id, expected, given=response.body) |
|
2767 | self._compare_ok(random_id, expected, given=response.body) | |
2767 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) not in pullrequest.get_reviewer_users() |
|
2768 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) not in pullrequest.get_reviewer_users() | |
2768 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) in pullrequest.get_reviewer_users() |
|
2769 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) in pullrequest.get_reviewer_users() | |
2769 |
|
2770 | |||
2770 | def test_api_edit_reviewers_add_remove_multiple(self): |
|
2771 | def test_api_edit_reviewers_add_remove_multiple(self): | |
2771 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2772 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2772 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2773 | pullrequest = db.PullRequest().get(pull_request_id) | |
2773 | prr = db.PullRequestReviewer(db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN), pullrequest) |
|
2774 | prr = db.PullRequestReviewer(db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN), pullrequest) | |
2774 | meta.Session().add(prr) |
|
2775 | meta.Session().add(prr) | |
2775 | meta.Session().commit() |
|
2776 | meta.Session().commit() | |
2776 | assert db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) in pullrequest.get_reviewer_users() |
|
2777 | assert db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) in pullrequest.get_reviewer_users() | |
2777 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2778 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2778 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) not in pullrequest.get_reviewer_users() |
|
2779 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) not in pullrequest.get_reviewer_users() | |
2779 |
|
2780 | |||
2780 | pullrequest.owner = self.test_user |
|
2781 | pullrequest.owner = self.test_user | |
2781 | random_id = random.randrange(1, 9999) |
|
2782 | random_id = random.randrange(1, 9999) | |
2782 | params = ascii_bytes(ext_json.dumps({ |
|
2783 | params = ascii_bytes(ext_json.dumps({ | |
2783 | "id": random_id, |
|
2784 | "id": random_id, | |
2784 | "api_key": self.apikey_regular, |
|
2785 | "api_key": self.apikey_regular, | |
2785 | "method": "edit_reviewers", |
|
2786 | "method": "edit_reviewers", | |
2786 | "args": {"pull_request_id": pull_request_id, |
|
2787 | "args": {"pull_request_id": pull_request_id, | |
2787 | "add": [ base.TEST_USER_REGULAR2_LOGIN ], |
|
2788 | "add": [ base.TEST_USER_REGULAR2_LOGIN ], | |
2788 | "remove": [ base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_ADMIN_LOGIN ], |
|
2789 | "remove": [ base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_ADMIN_LOGIN ], | |
2789 | }, |
|
2790 | }, | |
2790 | })) |
|
2791 | })) | |
2791 | response = api_call(self, params) |
|
2792 | response = api_call(self, params) | |
2792 |
|
2793 | |||
2793 | # list order depends on python sorting hash, which is randomized |
|
2794 | # list order depends on python sorting hash, which is randomized | |
2794 | assert set(ext_json.loads(response.body)['result']['added']) == set([base.TEST_USER_REGULAR2_LOGIN]) |
|
2795 | assert set(ext_json.loads(response.body)['result']['added']) == set([base.TEST_USER_REGULAR2_LOGIN]) | |
2795 | assert set(ext_json.loads(response.body)['result']['already_present']) == set() |
|
2796 | assert set(ext_json.loads(response.body)['result']['already_present']) == set() | |
2796 | assert set(ext_json.loads(response.body)['result']['removed']) == set([base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_ADMIN_LOGIN]) |
|
2797 | assert set(ext_json.loads(response.body)['result']['removed']) == set([base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_ADMIN_LOGIN]) | |
2797 | assert db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) not in pullrequest.get_reviewer_users() |
|
2798 | assert db.User.get_by_username(base.TEST_USER_ADMIN_LOGIN) not in pullrequest.get_reviewer_users() | |
2798 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) not in pullrequest.get_reviewer_users() |
|
2799 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) not in pullrequest.get_reviewer_users() | |
2799 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) in pullrequest.get_reviewer_users() |
|
2800 | assert db.User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) in pullrequest.get_reviewer_users() | |
2800 |
|
2801 | |||
2801 | def test_api_edit_reviewers_invalid_params(self): |
|
2802 | def test_api_edit_reviewers_invalid_params(self): | |
2802 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') |
|
2803 | pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'edit reviewer test') | |
2803 | pullrequest = db.PullRequest().get(pull_request_id) |
|
2804 | pullrequest = db.PullRequest().get(pull_request_id) | |
2804 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() |
|
2805 | assert db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in pullrequest.get_reviewer_users() | |
2805 |
|
2806 | |||
2806 | pullrequest.owner = db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) |
|
2807 | pullrequest.owner = db.User.get_by_username(base.TEST_USER_REGULAR_LOGIN) | |
2807 | random_id = random.randrange(1, 9999) |
|
2808 | random_id = random.randrange(1, 9999) | |
2808 | params = ascii_bytes(ext_json.dumps({ |
|
2809 | params = ascii_bytes(ext_json.dumps({ | |
2809 | "id": random_id, |
|
2810 | "id": random_id, | |
2810 | "api_key": self.apikey_regular, |
|
2811 | "api_key": self.apikey_regular, | |
2811 | "method": "edit_reviewers", |
|
2812 | "method": "edit_reviewers", | |
2812 | "args": {"pull_request_id": pull_request_id}, |
|
2813 | "args": {"pull_request_id": pull_request_id}, | |
2813 | })) |
|
2814 | })) | |
2814 | response = api_call(self, params) |
|
2815 | response = api_call(self, params) | |
2815 |
|
2816 | |||
2816 | self._compare_error(random_id, "Invalid request. Neither 'add' nor 'remove' is specified.", given=response.body) |
|
2817 | self._compare_error(random_id, "Invalid request. Neither 'add' nor 'remove' is specified.", given=response.body) | |
2817 | assert ext_json.loads(response.body)['result'] is None |
|
2818 | assert ext_json.loads(response.body)['result'] is None |
@@ -1,579 +1,577 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 | kallithea.tests.other.test_libs |
|
15 | kallithea.tests.other.test_libs | |
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
17 |
|
17 | |||
18 | Package for testing various lib/helper functions in kallithea |
|
18 | Package for testing various lib/helper functions in kallithea | |
19 |
|
19 | |||
20 | This file was forked by the Kallithea project in July 2014. |
|
20 | This file was forked by the Kallithea project in July 2014. | |
21 | Original author and date, and relevant copyright and licensing information is below: |
|
21 | Original author and date, and relevant copyright and licensing information is below: | |
22 | :created_on: Jun 9, 2011 |
|
22 | :created_on: Jun 9, 2011 | |
23 | :author: marcink |
|
23 | :author: marcink | |
24 | :copyright: (c) 2013 RhodeCode GmbH, and others. |
|
24 | :copyright: (c) 2013 RhodeCode GmbH, and others. | |
25 | :license: GPLv3, see LICENSE.md for more details. |
|
25 | :license: GPLv3, see LICENSE.md for more details. | |
26 | """ |
|
26 | """ | |
27 |
|
27 | |||
28 | import datetime |
|
28 | import datetime | |
29 | import hashlib |
|
29 | import hashlib | |
30 | import re |
|
30 | import re | |
31 |
|
31 | |||
32 | import mock |
|
32 | import mock | |
33 | import routes |
|
33 | import routes | |
34 | from dateutil import relativedelta |
|
34 | from dateutil import relativedelta | |
35 | from tg import request |
|
35 | from tg import request | |
36 | from tg.util.webtest import test_context |
|
36 | from tg.util.webtest import test_context | |
37 |
|
37 | |||
38 | import kallithea.lib.helpers as h |
|
38 | import kallithea.lib.helpers as h | |
39 | from kallithea.lib import webutils |
|
39 | from kallithea.lib import webutils | |
40 | from kallithea.lib.utils2 import AttributeDict, get_clone_url, safe_bytes |
|
40 | from kallithea.lib.utils2 import AttributeDict, get_clone_url, safe_bytes | |
41 | from kallithea.model import db |
|
41 | from kallithea.model import db | |
42 | from kallithea.tests import base |
|
42 | from kallithea.tests import base | |
43 |
|
43 | |||
44 |
|
44 | |||
45 | proto = 'http' |
|
45 | proto = 'http' | |
46 | TEST_URLS = [ |
|
46 | TEST_URLS = [ | |
47 | ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], |
|
47 | ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], | |
48 | '%s://127.0.0.1' % proto), |
|
48 | '%s://127.0.0.1' % proto), | |
49 | ('%s://username@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], |
|
49 | ('%s://username@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], | |
50 | '%s://127.0.0.1' % proto), |
|
50 | '%s://127.0.0.1' % proto), | |
51 | ('%s://username:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], |
|
51 | ('%s://username:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], | |
52 | '%s://127.0.0.1' % proto), |
|
52 | '%s://127.0.0.1' % proto), | |
53 | ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'], |
|
53 | ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'], | |
54 | '%s://127.0.0.1:8080' % proto), |
|
54 | '%s://127.0.0.1:8080' % proto), | |
55 | ('%s://example.com' % proto, ['%s://' % proto, 'example.com'], |
|
55 | ('%s://example.com' % proto, ['%s://' % proto, 'example.com'], | |
56 | '%s://example.com' % proto), |
|
56 | '%s://example.com' % proto), | |
57 | ('%s://user:pass@example.com:8080' % proto, ['%s://' % proto, 'example.com', |
|
57 | ('%s://user:pass@example.com:8080' % proto, ['%s://' % proto, 'example.com', | |
58 | '8080'], |
|
58 | '8080'], | |
59 | '%s://example.com:8080' % proto), |
|
59 | '%s://example.com:8080' % proto), | |
60 | ] |
|
60 | ] | |
61 |
|
61 | |||
62 | proto = 'https' |
|
62 | proto = 'https' | |
63 | TEST_URLS += [ |
|
63 | TEST_URLS += [ | |
64 | ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], |
|
64 | ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], | |
65 | '%s://127.0.0.1' % proto), |
|
65 | '%s://127.0.0.1' % proto), | |
66 | ('%s://username@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], |
|
66 | ('%s://username@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], | |
67 | '%s://127.0.0.1' % proto), |
|
67 | '%s://127.0.0.1' % proto), | |
68 | ('%s://username:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], |
|
68 | ('%s://username:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'], | |
69 | '%s://127.0.0.1' % proto), |
|
69 | '%s://127.0.0.1' % proto), | |
70 | ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'], |
|
70 | ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'], | |
71 | '%s://127.0.0.1:8080' % proto), |
|
71 | '%s://127.0.0.1:8080' % proto), | |
72 | ('%s://example.com' % proto, ['%s://' % proto, 'example.com'], |
|
72 | ('%s://example.com' % proto, ['%s://' % proto, 'example.com'], | |
73 | '%s://example.com' % proto), |
|
73 | '%s://example.com' % proto), | |
74 | ('%s://user:pass@example.com:8080' % proto, ['%s://' % proto, 'example.com', |
|
74 | ('%s://user:pass@example.com:8080' % proto, ['%s://' % proto, 'example.com', | |
75 | '8080'], |
|
75 | '8080'], | |
76 | '%s://example.com:8080' % proto), |
|
76 | '%s://example.com:8080' % proto), | |
77 | ] |
|
77 | ] | |
78 |
|
78 | |||
79 |
|
79 | |||
80 | class TestLibs(base.TestController): |
|
80 | class TestLibs(base.TestController): | |
81 |
|
81 | |||
82 | @base.parametrize('test_url,expected,expected_creds', TEST_URLS) |
|
82 | @base.parametrize('test_url,expected,expected_creds', TEST_URLS) | |
83 | def test_uri_filter(self, test_url, expected, expected_creds): |
|
83 | def test_uri_filter(self, test_url, expected, expected_creds): | |
84 | from kallithea.lib.utils2 import uri_filter |
|
84 | from kallithea.lib.utils2 import uri_filter | |
85 | assert uri_filter(test_url) == expected |
|
85 | assert uri_filter(test_url) == expected | |
86 |
|
86 | |||
87 | @base.parametrize('test_url,expected,expected_creds', TEST_URLS) |
|
87 | @base.parametrize('test_url,expected,expected_creds', TEST_URLS) | |
88 | def test_credentials_filter(self, test_url, expected, expected_creds): |
|
88 | def test_credentials_filter(self, test_url, expected, expected_creds): | |
89 | from kallithea.lib.utils2 import credentials_filter |
|
89 | from kallithea.lib.utils2 import credentials_filter | |
90 | assert credentials_filter(test_url) == expected_creds |
|
90 | assert credentials_filter(test_url) == expected_creds | |
91 |
|
91 | |||
92 | @base.parametrize('str_bool,expected', [ |
|
92 | @base.parametrize('str_bool,expected', [ | |
93 | ('t', True), |
|
93 | ('t', True), | |
94 | ('true', True), |
|
94 | ('true', True), | |
95 | ('y', True), |
|
95 | ('y', True), | |
96 | ('yes', True), |
|
96 | ('yes', True), | |
97 | ('on', True), |
|
97 | ('on', True), | |
98 | ('1', True), |
|
98 | ('1', True), | |
99 | ('Y', True), |
|
99 | ('Y', True), | |
100 | ('yeS', True), |
|
100 | ('yeS', True), | |
101 | ('Y', True), |
|
101 | ('Y', True), | |
102 | ('TRUE', True), |
|
102 | ('TRUE', True), | |
103 | ('T', True), |
|
103 | ('T', True), | |
104 | ('False', False), |
|
104 | ('False', False), | |
105 | ('F', False), |
|
105 | ('F', False), | |
106 | ('FALSE', False), |
|
106 | ('FALSE', False), | |
107 | ('0', False), |
|
107 | ('0', False), | |
108 | ]) |
|
108 | ]) | |
109 | def test_asbool(self, str_bool, expected): |
|
109 | def test_asbool(self, str_bool, expected): | |
110 | from kallithea.lib.utils2 import asbool |
|
110 | from kallithea.lib.utils2 import asbool | |
111 | assert asbool(str_bool) == expected |
|
111 | assert asbool(str_bool) == expected | |
112 |
|
112 | |||
113 | def test_mention_extractor(self): |
|
113 | def test_mention_extractor(self): | |
114 | sample = ( |
|
114 | sample = ( | |
115 | "@first hi there @world here's my email username@example.com " |
|
115 | "@first hi there @world here's my email username@example.com " | |
116 | "@lukaszb check @one_more22 it pls @ ttwelve @D[] @one@two@three " |
|
116 | "@lukaszb check @one_more22 it pls @ ttwelve @D[] @one@two@three " | |
117 | "@UPPER @cAmEL @2one_more22 @john please see this http://org.pl " |
|
117 | "@UPPER @cAmEL @2one_more22 @john please see this http://org.pl " | |
118 | "@marian.user just do it @marco-polo and next extract @marco_polo " |
|
118 | "@marian.user just do it @marco-polo and next extract @marco_polo " | |
119 | "user.dot hej ! not-needed maril@example.com" |
|
119 | "user.dot hej ! not-needed maril@example.com" | |
120 | ) |
|
120 | ) | |
121 |
|
121 | |||
122 | expected = set([ |
|
122 | expected = set([ | |
123 | '2one_more22', 'first', 'lukaszb', 'one', 'one_more22', 'UPPER', 'cAmEL', 'john', |
|
123 | '2one_more22', 'first', 'lukaszb', 'one', 'one_more22', 'UPPER', 'cAmEL', 'john', | |
124 | 'marian.user', 'marco-polo', 'marco_polo', 'world']) |
|
124 | 'marian.user', 'marco-polo', 'marco_polo', 'world']) | |
125 | assert expected == set(webutils.extract_mentioned_usernames(sample)) |
|
125 | assert expected == set(webutils.extract_mentioned_usernames(sample)) | |
126 |
|
126 | |||
127 | @base.parametrize('age_args,expected', [ |
|
127 | @base.parametrize('age_args,expected', [ | |
128 | (dict(), 'just now'), |
|
128 | (dict(), 'just now'), | |
129 | (dict(seconds= -1), '1 second ago'), |
|
129 | (dict(seconds= -1), '1 second ago'), | |
130 | (dict(seconds= -60 * 2), '2 minutes ago'), |
|
130 | (dict(seconds= -60 * 2), '2 minutes ago'), | |
131 | (dict(hours= -1), '1 hour ago'), |
|
131 | (dict(hours= -1), '1 hour ago'), | |
132 | (dict(hours= -24), '1 day ago'), |
|
132 | (dict(hours= -24), '1 day ago'), | |
133 | (dict(hours= -24 * 5), '5 days ago'), |
|
133 | (dict(hours= -24 * 5), '5 days ago'), | |
134 | (dict(months= -1), '1 month ago'), |
|
134 | (dict(months= -1), '1 month ago'), | |
135 | (dict(months= -1, days= -2), '1 month and 2 days ago'), |
|
135 | (dict(months= -1, days= -2), '1 month and 2 days ago'), | |
136 | (dict(months= -1, days= -20), '1 month and 19 days ago'), |
|
136 | (dict(months= -1, days= -20), '1 month and 19 days ago'), | |
137 | (dict(years= -1, months= -1), '1 year and 1 month ago'), |
|
137 | (dict(years= -1, months= -1), '1 year and 1 month ago'), | |
138 | (dict(years= -1, months= -10), '1 year and 10 months ago'), |
|
138 | (dict(years= -1, months= -10), '1 year and 10 months ago'), | |
139 | (dict(years= -2, months= -4), '2 years and 4 months ago'), |
|
139 | (dict(years= -2, months= -4), '2 years and 4 months ago'), | |
140 | (dict(years= -2, months= -11), '2 years and 11 months ago'), |
|
140 | (dict(years= -2, months= -11), '2 years and 11 months ago'), | |
141 | (dict(years= -3, months= -2), '3 years and 2 months ago'), |
|
141 | (dict(years= -3, months= -2), '3 years and 2 months ago'), | |
142 | ]) |
|
142 | ]) | |
143 | def test_age(self, age_args, expected): |
|
143 | def test_age(self, age_args, expected): | |
144 | from kallithea.lib.webutils import age |
|
144 | from kallithea.lib.webutils import age | |
145 | with test_context(self.app): |
|
145 | with test_context(self.app): | |
146 | n = datetime.datetime(year=2012, month=5, day=17) |
|
146 | n = datetime.datetime(year=2012, month=5, day=17) | |
147 |
|
|
147 | assert age(n + relativedelta.relativedelta(**age_args), now=n) == expected | |
148 | assert age(n + delt(**age_args), now=n) == expected |
|
|||
149 |
|
148 | |||
150 | @base.parametrize('age_args,expected', [ |
|
149 | @base.parametrize('age_args,expected', [ | |
151 | (dict(), 'just now'), |
|
150 | (dict(), 'just now'), | |
152 | (dict(seconds= -1), '1 second ago'), |
|
151 | (dict(seconds= -1), '1 second ago'), | |
153 | (dict(seconds= -60 * 2), '2 minutes ago'), |
|
152 | (dict(seconds= -60 * 2), '2 minutes ago'), | |
154 | (dict(hours= -1), '1 hour ago'), |
|
153 | (dict(hours= -1), '1 hour ago'), | |
155 | (dict(hours= -24), '1 day ago'), |
|
154 | (dict(hours= -24), '1 day ago'), | |
156 | (dict(hours= -24 * 5), '5 days ago'), |
|
155 | (dict(hours= -24 * 5), '5 days ago'), | |
157 | (dict(months= -1), '1 month ago'), |
|
156 | (dict(months= -1), '1 month ago'), | |
158 | (dict(months= -1, days= -2), '1 month ago'), |
|
157 | (dict(months= -1, days= -2), '1 month ago'), | |
159 | (dict(months= -1, days= -20), '1 month ago'), |
|
158 | (dict(months= -1, days= -20), '1 month ago'), | |
160 | (dict(years= -1, months= -1), '13 months ago'), |
|
159 | (dict(years= -1, months= -1), '13 months ago'), | |
161 | (dict(years= -1, months= -10), '22 months ago'), |
|
160 | (dict(years= -1, months= -10), '22 months ago'), | |
162 | (dict(years= -2, months= -4), '2 years ago'), |
|
161 | (dict(years= -2, months= -4), '2 years ago'), | |
163 | (dict(years= -2, months= -11), '3 years ago'), |
|
162 | (dict(years= -2, months= -11), '3 years ago'), | |
164 | (dict(years= -3, months= -2), '3 years ago'), |
|
163 | (dict(years= -3, months= -2), '3 years ago'), | |
165 | (dict(years= -4, months= -8), '5 years ago'), |
|
164 | (dict(years= -4, months= -8), '5 years ago'), | |
166 | ]) |
|
165 | ]) | |
167 | def test_age_short(self, age_args, expected): |
|
166 | def test_age_short(self, age_args, expected): | |
168 | from kallithea.lib.webutils import age |
|
167 | from kallithea.lib.webutils import age | |
169 | with test_context(self.app): |
|
168 | with test_context(self.app): | |
170 | n = datetime.datetime(year=2012, month=5, day=17) |
|
169 | n = datetime.datetime(year=2012, month=5, day=17) | |
171 | delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs) |
|
170 | assert age(n + relativedelta.relativedelta(**age_args), show_short_version=True, now=n) == expected | |
172 | assert age(n + delt(**age_args), show_short_version=True, now=n) == expected |
|
|||
173 |
|
171 | |||
174 | @base.parametrize('age_args,expected', [ |
|
172 | @base.parametrize('age_args,expected', [ | |
175 | (dict(), 'just now'), |
|
173 | (dict(), 'just now'), | |
176 | (dict(seconds=1), 'in 1 second'), |
|
174 | (dict(seconds=1), 'in 1 second'), | |
177 | (dict(seconds=60 * 2), 'in 2 minutes'), |
|
175 | (dict(seconds=60 * 2), 'in 2 minutes'), | |
178 | (dict(hours=1), 'in 1 hour'), |
|
176 | (dict(hours=1), 'in 1 hour'), | |
179 | (dict(hours=24), 'in 1 day'), |
|
177 | (dict(hours=24), 'in 1 day'), | |
180 | (dict(hours=24 * 5), 'in 5 days'), |
|
178 | (dict(hours=24 * 5), 'in 5 days'), | |
181 | (dict(months=1), 'in 1 month'), |
|
179 | (dict(months=1), 'in 1 month'), | |
182 | (dict(months=1, days=1), 'in 1 month and 1 day'), |
|
180 | (dict(months=1, days=1), 'in 1 month and 1 day'), | |
183 | (dict(years=1, months=1), 'in 1 year and 1 month') |
|
181 | (dict(years=1, months=1), 'in 1 year and 1 month') | |
184 | ]) |
|
182 | ]) | |
185 | def test_age_in_future(self, age_args, expected): |
|
183 | def test_age_in_future(self, age_args, expected): | |
186 | from kallithea.lib.webutils import age |
|
184 | from kallithea.lib.webutils import age | |
187 | with test_context(self.app): |
|
185 | with test_context(self.app): | |
188 | n = datetime.datetime(year=2012, month=5, day=17) |
|
186 | n = datetime.datetime(year=2012, month=5, day=17) | |
189 |
|
|
187 | assert age(n + relativedelta.relativedelta(**age_args), now=n) == expected | |
190 | assert age(n + delt(**age_args), now=n) == expected |
|
|||
191 |
|
188 | |||
192 | def test_tag_extractor(self): |
|
189 | def test_tag_extractor(self): | |
193 | sample = ( |
|
190 | sample = ( | |
194 | "hello pta[tag] gog [[]] [[] sda ero[or]d [me =>>< sa]" |
|
191 | "hello pta[tag] gog [[]] [[] sda ero[or]d [me =>>< sa]" | |
195 | "[requires] [stale] [see<>=>] [see => http://example.com]" |
|
192 | "[requires] [stale] [see<>=>] [see => http://example.com]" | |
196 | "[requires => url] [lang => python] [just a tag]" |
|
193 | "[requires => url] [lang => python] [just a tag]" | |
197 | "[,d] [ => ULR ] [obsolete] [desc]]" |
|
194 | "[,d] [ => ULR ] [obsolete] [desc]]" | |
198 | ) |
|
195 | ) | |
199 | res = webutils.urlify_text(sample, stylize=True) |
|
196 | res = webutils.urlify_text(sample, stylize=True) | |
200 | assert '<div class="label label-meta" data-tag="tag">tag</div>' in res |
|
197 | assert '<div class="label label-meta" data-tag="tag">tag</div>' in res | |
201 | assert '<div class="label label-meta" data-tag="obsolete">obsolete</div>' in res |
|
198 | assert '<div class="label label-meta" data-tag="obsolete">obsolete</div>' in res | |
202 | assert '<div class="label label-meta" data-tag="stale">stale</div>' in res |
|
199 | assert '<div class="label label-meta" data-tag="stale">stale</div>' in res | |
203 | assert '<div class="label label-meta" data-tag="lang">python</div>' in res |
|
200 | assert '<div class="label label-meta" data-tag="lang">python</div>' in res | |
204 | assert '<div class="label label-meta" data-tag="requires">requires => <a href="/url">url</a></div>' in res |
|
201 | assert '<div class="label label-meta" data-tag="requires">requires => <a href="/url">url</a></div>' in res | |
205 | assert '<div class="label label-meta" data-tag="tag">tag</div>' in res |
|
202 | assert '<div class="label label-meta" data-tag="tag">tag</div>' in res | |
206 |
|
203 | |||
207 | def test_alternative_gravatar(self): |
|
204 | def test_alternative_gravatar(self): | |
208 | _md5 = lambda s: hashlib.md5(safe_bytes(s)).hexdigest() |
|
205 | def _md5(s): | |
|
206 | return hashlib.md5(safe_bytes(s)).hexdigest() | |||
209 |
|
207 | |||
210 | # mock tg.tmpl_context |
|
208 | # mock tg.tmpl_context | |
211 | def fake_tmpl_context(_url): |
|
209 | def fake_tmpl_context(_url): | |
212 | _c = AttributeDict() |
|
210 | _c = AttributeDict() | |
213 | _c.visual = AttributeDict() |
|
211 | _c.visual = AttributeDict() | |
214 | _c.visual.use_gravatar = True |
|
212 | _c.visual.use_gravatar = True | |
215 | _c.visual.gravatar_url = _url |
|
213 | _c.visual.gravatar_url = _url | |
216 |
|
214 | |||
217 | return _c |
|
215 | return _c | |
218 |
|
216 | |||
219 | with mock.patch('kallithea.lib.webutils.url.current', lambda *a, **b: 'https://example.com'): |
|
217 | with mock.patch('kallithea.lib.webutils.url.current', lambda *a, **b: 'https://example.com'): | |
220 | fake = fake_tmpl_context(_url='http://example.com/{email}') |
|
218 | fake = fake_tmpl_context(_url='http://example.com/{email}') | |
221 | with mock.patch('kallithea.lib.helpers.c', fake): |
|
219 | with mock.patch('kallithea.lib.helpers.c', fake): | |
222 | assert webutils.url.current() == 'https://example.com' |
|
220 | assert webutils.url.current() == 'https://example.com' | |
223 | grav = h.gravatar_url(email_address='test@example.com', size=24) |
|
221 | grav = h.gravatar_url(email_address='test@example.com', size=24) | |
224 | assert grav == 'http://example.com/test@example.com' |
|
222 | assert grav == 'http://example.com/test@example.com' | |
225 |
|
223 | |||
226 | fake = fake_tmpl_context(_url='http://example.com/{email}') |
|
224 | fake = fake_tmpl_context(_url='http://example.com/{email}') | |
227 | with mock.patch('kallithea.lib.helpers.c', fake): |
|
225 | with mock.patch('kallithea.lib.helpers.c', fake): | |
228 | grav = h.gravatar_url(email_address='test@example.com', size=24) |
|
226 | grav = h.gravatar_url(email_address='test@example.com', size=24) | |
229 | assert grav == 'http://example.com/test@example.com' |
|
227 | assert grav == 'http://example.com/test@example.com' | |
230 |
|
228 | |||
231 | fake = fake_tmpl_context(_url='http://example.com/{md5email}') |
|
229 | fake = fake_tmpl_context(_url='http://example.com/{md5email}') | |
232 | with mock.patch('kallithea.lib.helpers.c', fake): |
|
230 | with mock.patch('kallithea.lib.helpers.c', fake): | |
233 | em = 'test@example.com' |
|
231 | em = 'test@example.com' | |
234 | grav = h.gravatar_url(email_address=em, size=24) |
|
232 | grav = h.gravatar_url(email_address=em, size=24) | |
235 | assert grav == 'http://example.com/%s' % (_md5(em)) |
|
233 | assert grav == 'http://example.com/%s' % (_md5(em)) | |
236 |
|
234 | |||
237 | fake = fake_tmpl_context(_url='http://example.com/{md5email}/{size}') |
|
235 | fake = fake_tmpl_context(_url='http://example.com/{md5email}/{size}') | |
238 | with mock.patch('kallithea.lib.helpers.c', fake): |
|
236 | with mock.patch('kallithea.lib.helpers.c', fake): | |
239 | em = 'test@example.com' |
|
237 | em = 'test@example.com' | |
240 | grav = h.gravatar_url(email_address=em, size=24) |
|
238 | grav = h.gravatar_url(email_address=em, size=24) | |
241 | assert grav == 'http://example.com/%s/%s' % (_md5(em), 24) |
|
239 | assert grav == 'http://example.com/%s/%s' % (_md5(em), 24) | |
242 |
|
240 | |||
243 | fake = fake_tmpl_context(_url='{scheme}://{netloc}/{md5email}/{size}') |
|
241 | fake = fake_tmpl_context(_url='{scheme}://{netloc}/{md5email}/{size}') | |
244 | with mock.patch('kallithea.lib.helpers.c', fake): |
|
242 | with mock.patch('kallithea.lib.helpers.c', fake): | |
245 | em = 'test@example.com' |
|
243 | em = 'test@example.com' | |
246 | grav = h.gravatar_url(email_address=em, size=24) |
|
244 | grav = h.gravatar_url(email_address=em, size=24) | |
247 | assert grav == 'https://example.com/%s/%s' % (_md5(em), 24) |
|
245 | assert grav == 'https://example.com/%s/%s' % (_md5(em), 24) | |
248 |
|
246 | |||
249 | @base.parametrize('clone_uri_tmpl,repo_name,username,prefix,expected', [ |
|
247 | @base.parametrize('clone_uri_tmpl,repo_name,username,prefix,expected', [ | |
250 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', None, '', 'http://vps1:8000/group/repo1'), |
|
248 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', None, '', 'http://vps1:8000/group/repo1'), | |
251 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', 'username', '', 'http://username@vps1:8000/group/repo1'), |
|
249 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', 'username', '', 'http://username@vps1:8000/group/repo1'), | |
252 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', None, '/prefix', 'http://vps1:8000/prefix/group/repo1'), |
|
250 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', None, '/prefix', 'http://vps1:8000/prefix/group/repo1'), | |
253 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', 'user', '/prefix', 'http://user@vps1:8000/prefix/group/repo1'), |
|
251 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', 'user', '/prefix', 'http://user@vps1:8000/prefix/group/repo1'), | |
254 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', 'username', '/prefix', 'http://username@vps1:8000/prefix/group/repo1'), |
|
252 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', 'username', '/prefix', 'http://username@vps1:8000/prefix/group/repo1'), | |
255 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', 'user', '/prefix/', 'http://user@vps1:8000/prefix/group/repo1'), |
|
253 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', 'user', '/prefix/', 'http://user@vps1:8000/prefix/group/repo1'), | |
256 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', 'username', '/prefix/', 'http://username@vps1:8000/prefix/group/repo1'), |
|
254 | (db.Repository.DEFAULT_CLONE_URI, 'group/repo1', 'username', '/prefix/', 'http://username@vps1:8000/prefix/group/repo1'), | |
257 | ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', None, '', 'http://vps1:8000/_23'), |
|
255 | ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', None, '', 'http://vps1:8000/_23'), | |
258 | ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', 'username', '', 'http://username@vps1:8000/_23'), |
|
256 | ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', 'username', '', 'http://username@vps1:8000/_23'), | |
259 | ('http://{user}@{netloc}/_{repoid}', 'group/repo1', 'username', '', 'http://username@vps1:8000/_23'), |
|
257 | ('http://{user}@{netloc}/_{repoid}', 'group/repo1', 'username', '', 'http://username@vps1:8000/_23'), | |
260 | ('http://{netloc}/_{repoid}', 'group/repo1', 'username', '', 'http://vps1:8000/_23'), |
|
258 | ('http://{netloc}/_{repoid}', 'group/repo1', 'username', '', 'http://vps1:8000/_23'), | |
261 | ('https://{user}@proxy1.example.com/{repo}', 'group/repo1', 'username', '', 'https://username@proxy1.example.com/group/repo1'), |
|
259 | ('https://{user}@proxy1.example.com/{repo}', 'group/repo1', 'username', '', 'https://username@proxy1.example.com/group/repo1'), | |
262 | ('https://{user}@proxy1.example.com/{repo}', 'group/repo1', None, '', 'https://proxy1.example.com/group/repo1'), |
|
260 | ('https://{user}@proxy1.example.com/{repo}', 'group/repo1', None, '', 'https://proxy1.example.com/group/repo1'), | |
263 | ('https://proxy1.example.com/{user}/{repo}', 'group/repo1', 'username', '', 'https://proxy1.example.com/username/group/repo1'), |
|
261 | ('https://proxy1.example.com/{user}/{repo}', 'group/repo1', 'username', '', 'https://proxy1.example.com/username/group/repo1'), | |
264 | ]) |
|
262 | ]) | |
265 | def test_clone_url_generator(self, clone_uri_tmpl, repo_name, username, prefix, expected): |
|
263 | def test_clone_url_generator(self, clone_uri_tmpl, repo_name, username, prefix, expected): | |
266 | clone_url = get_clone_url(clone_uri_tmpl=clone_uri_tmpl, prefix_url='http://vps1:8000' + prefix, |
|
264 | clone_url = get_clone_url(clone_uri_tmpl=clone_uri_tmpl, prefix_url='http://vps1:8000' + prefix, | |
267 | repo_name=repo_name, repo_id=23, username=username) |
|
265 | repo_name=repo_name, repo_id=23, username=username) | |
268 | assert clone_url == expected |
|
266 | assert clone_url == expected | |
269 |
|
267 | |||
270 | def _quick_url(self, text, tmpl="""<a class="changeset_hash" href="%s">%s</a>""", url_=None): |
|
268 | def _quick_url(self, text, tmpl="""<a class="changeset_hash" href="%s">%s</a>""", url_=None): | |
271 | """ |
|
269 | """ | |
272 | Changes `some text url[foo]` => `some text <a href="/">foo</a> |
|
270 | Changes `some text url[foo]` => `some text <a href="/">foo</a> | |
273 |
|
271 | |||
274 | :param text: |
|
272 | :param text: | |
275 | """ |
|
273 | """ | |
276 | # quickly change expected url[] into a link |
|
274 | # quickly change expected url[] into a link | |
277 | url_pattern = re.compile(r'(?:url\[)(.+?)(?:\])') |
|
275 | url_pattern = re.compile(r'(?:url\[)(.+?)(?:\])') | |
278 |
|
276 | |||
279 | def url_func(match_obj): |
|
277 | def url_func(match_obj): | |
280 | _url = match_obj.groups()[0] |
|
278 | _url = match_obj.groups()[0] | |
281 | return tmpl % (url_ or '/repo_name/changeset/%s' % _url, _url) |
|
279 | return tmpl % (url_ or '/repo_name/changeset/%s' % _url, _url) | |
282 | return url_pattern.sub(url_func, text) |
|
280 | return url_pattern.sub(url_func, text) | |
283 |
|
281 | |||
284 | @base.parametrize('sample,expected', [ |
|
282 | @base.parametrize('sample,expected', [ | |
285 | ("", |
|
283 | ("", | |
286 | ""), |
|
284 | ""), | |
287 | ("git-svn-id: https://svn.apache.org/repos/asf/libcloud/trunk@1441655 13f79535-47bb-0310-9956-ffa450edef68", |
|
285 | ("git-svn-id: https://svn.apache.org/repos/asf/libcloud/trunk@1441655 13f79535-47bb-0310-9956-ffa450edef68", | |
288 | """git-svn-id: <a href="https://svn.apache.org/repos/asf/libcloud/trunk@1441655">https://svn.apache.org/repos/asf/libcloud/trunk@1441655</a> 13f79535-47bb-0310-9956-ffa450edef68"""), |
|
286 | """git-svn-id: <a href="https://svn.apache.org/repos/asf/libcloud/trunk@1441655">https://svn.apache.org/repos/asf/libcloud/trunk@1441655</a> 13f79535-47bb-0310-9956-ffa450edef68"""), | |
289 | ("from rev 000000000000", |
|
287 | ("from rev 000000000000", | |
290 | """from rev url[000000000000]"""), |
|
288 | """from rev url[000000000000]"""), | |
291 | ("from rev 000000000000123123 also rev 000000000000", |
|
289 | ("from rev 000000000000123123 also rev 000000000000", | |
292 | """from rev url[000000000000123123] also rev url[000000000000]"""), |
|
290 | """from rev url[000000000000123123] also rev url[000000000000]"""), | |
293 | ("this should-000 00", |
|
291 | ("this should-000 00", | |
294 | """this should-000 00"""), |
|
292 | """this should-000 00"""), | |
295 | ("longtextffffffffff rev 123123123123", |
|
293 | ("longtextffffffffff rev 123123123123", | |
296 | """longtextffffffffff rev url[123123123123]"""), |
|
294 | """longtextffffffffff rev url[123123123123]"""), | |
297 | ("rev ffffffffffffffffffffffffffffffffffffffffffffffffff", |
|
295 | ("rev ffffffffffffffffffffffffffffffffffffffffffffffffff", | |
298 | """rev ffffffffffffffffffffffffffffffffffffffffffffffffff"""), |
|
296 | """rev ffffffffffffffffffffffffffffffffffffffffffffffffff"""), | |
299 | ("ffffffffffff some text traalaa", |
|
297 | ("ffffffffffff some text traalaa", | |
300 | """url[ffffffffffff] some text traalaa"""), |
|
298 | """url[ffffffffffff] some text traalaa"""), | |
301 | ("""Multi line |
|
299 | ("""Multi line | |
302 | 123123123123 |
|
300 | 123123123123 | |
303 | some text 123123123123 |
|
301 | some text 123123123123 | |
304 | sometimes ! |
|
302 | sometimes ! | |
305 | """, |
|
303 | """, | |
306 | """Multi line<br/>""" |
|
304 | """Multi line<br/>""" | |
307 | """ url[123123123123]<br/>""" |
|
305 | """ url[123123123123]<br/>""" | |
308 | """ some text url[123123123123]<br/>""" |
|
306 | """ some text url[123123123123]<br/>""" | |
309 | """ sometimes !"""), |
|
307 | """ sometimes !"""), | |
310 | ]) |
|
308 | ]) | |
311 | def test_urlify_text(self, sample, expected): |
|
309 | def test_urlify_text(self, sample, expected): | |
312 | expected = self._quick_url(expected) |
|
310 | expected = self._quick_url(expected) | |
313 |
|
311 | |||
314 | with mock.patch('kallithea.lib.webutils.UrlGenerator.__call__', |
|
312 | with mock.patch('kallithea.lib.webutils.UrlGenerator.__call__', | |
315 | lambda self, name, **kwargs: dict(changeset_home='/%(repo_name)s/changeset/%(revision)s')[name] % kwargs, |
|
313 | lambda self, name, **kwargs: dict(changeset_home='/%(repo_name)s/changeset/%(revision)s')[name] % kwargs, | |
316 | ): |
|
314 | ): | |
317 | assert webutils.urlify_text(sample, 'repo_name') == expected |
|
315 | assert webutils.urlify_text(sample, 'repo_name') == expected | |
318 |
|
316 | |||
319 | @base.parametrize('sample,expected,url_', [ |
|
317 | @base.parametrize('sample,expected,url_', [ | |
320 | ("", |
|
318 | ("", | |
321 | "", |
|
319 | "", | |
322 | ""), |
|
320 | ""), | |
323 | ("https://svn.apache.org/repos", |
|
321 | ("https://svn.apache.org/repos", | |
324 | """url[https://svn.apache.org/repos]""", |
|
322 | """url[https://svn.apache.org/repos]""", | |
325 | "https://svn.apache.org/repos"), |
|
323 | "https://svn.apache.org/repos"), | |
326 | ("http://svn.apache.org/repos", |
|
324 | ("http://svn.apache.org/repos", | |
327 | """url[http://svn.apache.org/repos]""", |
|
325 | """url[http://svn.apache.org/repos]""", | |
328 | "http://svn.apache.org/repos"), |
|
326 | "http://svn.apache.org/repos"), | |
329 | ("from rev a also rev http://google.com", |
|
327 | ("from rev a also rev http://google.com", | |
330 | """from rev a also rev url[http://google.com]""", |
|
328 | """from rev a also rev url[http://google.com]""", | |
331 | "http://google.com"), |
|
329 | "http://google.com"), | |
332 | ("http://imgur.com/foo.gif inline http://imgur.com/foo.gif ending http://imgur.com/foo.gif", |
|
330 | ("http://imgur.com/foo.gif inline http://imgur.com/foo.gif ending http://imgur.com/foo.gif", | |
333 | """url[http://imgur.com/foo.gif] inline url[http://imgur.com/foo.gif] ending url[http://imgur.com/foo.gif]""", |
|
331 | """url[http://imgur.com/foo.gif] inline url[http://imgur.com/foo.gif] ending url[http://imgur.com/foo.gif]""", | |
334 | "http://imgur.com/foo.gif"), |
|
332 | "http://imgur.com/foo.gif"), | |
335 | ("""Multi line |
|
333 | ("""Multi line | |
336 | https://foo.bar.example.com |
|
334 | https://foo.bar.example.com | |
337 | some text lalala""", |
|
335 | some text lalala""", | |
338 | """Multi line<br/>""" |
|
336 | """Multi line<br/>""" | |
339 | """ url[https://foo.bar.example.com]<br/>""" |
|
337 | """ url[https://foo.bar.example.com]<br/>""" | |
340 | """ some text lalala""", |
|
338 | """ some text lalala""", | |
341 | "https://foo.bar.example.com"), |
|
339 | "https://foo.bar.example.com"), | |
342 | ("@mention @someone", |
|
340 | ("@mention @someone", | |
343 | """<b>@mention</b> <b>@someone</b>""", |
|
341 | """<b>@mention</b> <b>@someone</b>""", | |
344 | ""), |
|
342 | ""), | |
345 | ("deadbeefcafe 123412341234", |
|
343 | ("deadbeefcafe 123412341234", | |
346 | """<a class="changeset_hash" href="/repo_name/changeset/deadbeefcafe">deadbeefcafe</a> <a class="changeset_hash" href="/repo_name/changeset/123412341234">123412341234</a>""", |
|
344 | """<a class="changeset_hash" href="/repo_name/changeset/deadbeefcafe">deadbeefcafe</a> <a class="changeset_hash" href="/repo_name/changeset/123412341234">123412341234</a>""", | |
347 | ""), |
|
345 | ""), | |
348 | ("We support * markup for *bold* markup of *single or multiple* words, " |
|
346 | ("We support * markup for *bold* markup of *single or multiple* words, " | |
349 | "*a bit @like http://slack.com*. " |
|
347 | "*a bit @like http://slack.com*. " | |
350 | "The first * must come after whitespace and not be followed by whitespace, " |
|
348 | "The first * must come after whitespace and not be followed by whitespace, " | |
351 | "contain anything but * and newline until the next *, " |
|
349 | "contain anything but * and newline until the next *, " | |
352 | "which must not come after whitespace " |
|
350 | "which must not come after whitespace " | |
353 | "and not be followed by * or alphanumerical *characters*.", |
|
351 | "and not be followed by * or alphanumerical *characters*.", | |
354 | """We support * markup for <b>*bold*</b> markup of <b>*single or multiple*</b> words, """ |
|
352 | """We support * markup for <b>*bold*</b> markup of <b>*single or multiple*</b> words, """ | |
355 | """<b>*a bit <b>@like</b> <a href="http://slack.com">http://slack.com</a>*</b>. """ |
|
353 | """<b>*a bit <b>@like</b> <a href="http://slack.com">http://slack.com</a>*</b>. """ | |
356 | """The first * must come after whitespace and not be followed by whitespace, """ |
|
354 | """The first * must come after whitespace and not be followed by whitespace, """ | |
357 | """contain anything but * and newline until the next *, """ |
|
355 | """contain anything but * and newline until the next *, """ | |
358 | """which must not come after whitespace """ |
|
356 | """which must not come after whitespace """ | |
359 | """and not be followed by * or alphanumerical <b>*characters*</b>.""", |
|
357 | """and not be followed by * or alphanumerical <b>*characters*</b>.""", | |
360 | "-"), |
|
358 | "-"), | |
361 | ("HTML escaping: <abc> 'single' \"double\" &pointer", |
|
359 | ("HTML escaping: <abc> 'single' \"double\" &pointer", | |
362 | "HTML escaping: <abc> 'single' "double" &pointer", |
|
360 | "HTML escaping: <abc> 'single' "double" &pointer", | |
363 | "-"), |
|
361 | "-"), | |
364 | # tags are covered by test_tag_extractor |
|
362 | # tags are covered by test_tag_extractor | |
365 | ]) |
|
363 | ]) | |
366 | def test_urlify_test(self, sample, expected, url_): |
|
364 | def test_urlify_test(self, sample, expected, url_): | |
367 | expected = self._quick_url(expected, |
|
365 | expected = self._quick_url(expected, | |
368 | tmpl="""<a href="%s">%s</a>""", url_=url_) |
|
366 | tmpl="""<a href="%s">%s</a>""", url_=url_) | |
369 | with mock.patch('kallithea.lib.webutils.UrlGenerator.__call__', |
|
367 | with mock.patch('kallithea.lib.webutils.UrlGenerator.__call__', | |
370 | lambda self, name, **kwargs: dict(changeset_home='/%(repo_name)s/changeset/%(revision)s')[name] % kwargs, |
|
368 | lambda self, name, **kwargs: dict(changeset_home='/%(repo_name)s/changeset/%(revision)s')[name] % kwargs, | |
371 | ): |
|
369 | ): | |
372 | assert webutils.urlify_text(sample, 'repo_name', stylize=True) == expected |
|
370 | assert webutils.urlify_text(sample, 'repo_name', stylize=True) == expected | |
373 |
|
371 | |||
374 | @base.parametrize('sample,expected', [ |
|
372 | @base.parametrize('sample,expected', [ | |
375 | ("deadbeefcafe @mention, and http://foo.bar/ yo", |
|
373 | ("deadbeefcafe @mention, and http://foo.bar/ yo", | |
376 | """<a class="changeset_hash" href="/repo_name/changeset/deadbeefcafe">deadbeefcafe</a>""" |
|
374 | """<a class="changeset_hash" href="/repo_name/changeset/deadbeefcafe">deadbeefcafe</a>""" | |
377 | """<a class="message-link" href="#the-link"> <b>@mention</b>, and </a>""" |
|
375 | """<a class="message-link" href="#the-link"> <b>@mention</b>, and </a>""" | |
378 | """<a href="http://foo.bar/">http://foo.bar/</a>""" |
|
376 | """<a href="http://foo.bar/">http://foo.bar/</a>""" | |
379 | """<a class="message-link" href="#the-link"> yo</a>"""), |
|
377 | """<a class="message-link" href="#the-link"> yo</a>"""), | |
380 | ]) |
|
378 | ]) | |
381 | def test_urlify_link(self, sample, expected): |
|
379 | def test_urlify_link(self, sample, expected): | |
382 | with mock.patch('kallithea.lib.webutils.UrlGenerator.__call__', |
|
380 | with mock.patch('kallithea.lib.webutils.UrlGenerator.__call__', | |
383 | lambda self, name, **kwargs: dict(changeset_home='/%(repo_name)s/changeset/%(revision)s')[name] % kwargs, |
|
381 | lambda self, name, **kwargs: dict(changeset_home='/%(repo_name)s/changeset/%(revision)s')[name] % kwargs, | |
384 | ): |
|
382 | ): | |
385 | assert webutils.urlify_text(sample, 'repo_name', link_='#the-link') == expected |
|
383 | assert webutils.urlify_text(sample, 'repo_name', link_='#the-link') == expected | |
386 |
|
384 | |||
387 | @base.parametrize('issue_pat,issue_server,issue_sub,sample,expected', [ |
|
385 | @base.parametrize('issue_pat,issue_server,issue_sub,sample,expected', [ | |
388 | (r'#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', |
|
386 | (r'#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', | |
389 | 'issue #123 and issue#456', |
|
387 | 'issue #123 and issue#456', | |
390 | """issue <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> and """ |
|
388 | """issue <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> and """ | |
391 | """issue<a class="issue-tracker-link" href="http://foo/repo_name/issue/456">#456</a>"""), |
|
389 | """issue<a class="issue-tracker-link" href="http://foo/repo_name/issue/456">#456</a>"""), | |
392 | (r'(?:\s*#)(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', |
|
390 | (r'(?:\s*#)(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', | |
393 | 'issue #123 and issue#456', |
|
391 | 'issue #123 and issue#456', | |
394 | """issue<a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> and """ |
|
392 | """issue<a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> and """ | |
395 | """issue<a class="issue-tracker-link" href="http://foo/repo_name/issue/456">#456</a>"""), |
|
393 | """issue<a class="issue-tracker-link" href="http://foo/repo_name/issue/456">#456</a>"""), | |
396 | # to require whitespace before the issue reference, one may be tempted to use \b... |
|
394 | # to require whitespace before the issue reference, one may be tempted to use \b... | |
397 | (r'\bPR(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', |
|
395 | (r'\bPR(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', | |
398 | 'issue PR123 and issuePR456', |
|
396 | 'issue PR123 and issuePR456', | |
399 | """issue <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> and """ |
|
397 | """issue <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> and """ | |
400 | """issuePR456"""), |
|
398 | """issuePR456"""), | |
401 | # ... but it turns out that \b does not work well in combination with '#': the expectations |
|
399 | # ... but it turns out that \b does not work well in combination with '#': the expectations | |
402 | # are reversed from what is actually happening. |
|
400 | # are reversed from what is actually happening. | |
403 | (r'\b#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', |
|
401 | (r'\b#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', | |
404 | 'issue #123 and issue#456', |
|
402 | 'issue #123 and issue#456', | |
405 | """issue #123 and """ |
|
403 | """issue #123 and """ | |
406 | """issue<a class="issue-tracker-link" href="http://foo/repo_name/issue/456">#456</a>"""), |
|
404 | """issue<a class="issue-tracker-link" href="http://foo/repo_name/issue/456">#456</a>"""), | |
407 | # ... so maybe try to be explicit? Unfortunately the whitespace before the issue |
|
405 | # ... so maybe try to be explicit? Unfortunately the whitespace before the issue | |
408 | # reference is not retained, again, because it is part of the pattern. |
|
406 | # reference is not retained, again, because it is part of the pattern. | |
409 | (r'(?:^|\s)#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', |
|
407 | (r'(?:^|\s)#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', | |
410 | '#15 and issue #123 and issue#456', |
|
408 | '#15 and issue #123 and issue#456', | |
411 | """<a class="issue-tracker-link" href="http://foo/repo_name/issue/15">#15</a> and """ |
|
409 | """<a class="issue-tracker-link" href="http://foo/repo_name/issue/15">#15</a> and """ | |
412 | """issue<a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> and """ |
|
410 | """issue<a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> and """ | |
413 | """issue#456"""), |
|
411 | """issue#456"""), | |
414 | # ... instead, use lookbehind assertions. |
|
412 | # ... instead, use lookbehind assertions. | |
415 | (r'(?:^|(?<=\s))#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', |
|
413 | (r'(?:^|(?<=\s))#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', | |
416 | '#15 and issue #123 and issue#456', |
|
414 | '#15 and issue #123 and issue#456', | |
417 | """<a class="issue-tracker-link" href="http://foo/repo_name/issue/15">#15</a> and """ |
|
415 | """<a class="issue-tracker-link" href="http://foo/repo_name/issue/15">#15</a> and """ | |
418 | """issue <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> and """ |
|
416 | """issue <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> and """ | |
419 | """issue#456"""), |
|
417 | """issue#456"""), | |
420 | (r'(?:pullrequest|pull request|PR|pr) ?#?(\d+)', 'http://foo/{repo}/issue/\\1', 'PR#\\1', |
|
418 | (r'(?:pullrequest|pull request|PR|pr) ?#?(\d+)', 'http://foo/{repo}/issue/\\1', 'PR#\\1', | |
421 | 'fixed with pullrequest #1, pull request#2, PR 3, pr4', |
|
419 | 'fixed with pullrequest #1, pull request#2, PR 3, pr4', | |
422 | """fixed with <a class="issue-tracker-link" href="http://foo/repo_name/issue/1">PR#1</a>, """ |
|
420 | """fixed with <a class="issue-tracker-link" href="http://foo/repo_name/issue/1">PR#1</a>, """ | |
423 | """<a class="issue-tracker-link" href="http://foo/repo_name/issue/2">PR#2</a>, """ |
|
421 | """<a class="issue-tracker-link" href="http://foo/repo_name/issue/2">PR#2</a>, """ | |
424 | """<a class="issue-tracker-link" href="http://foo/repo_name/issue/3">PR#3</a>, """ |
|
422 | """<a class="issue-tracker-link" href="http://foo/repo_name/issue/3">PR#3</a>, """ | |
425 | """<a class="issue-tracker-link" href="http://foo/repo_name/issue/4">PR#4</a>"""), |
|
423 | """<a class="issue-tracker-link" href="http://foo/repo_name/issue/4">PR#4</a>"""), | |
426 | (r'#(\d+)', 'http://foo/{repo}/issue/\\1', 'PR\\1', |
|
424 | (r'#(\d+)', 'http://foo/{repo}/issue/\\1', 'PR\\1', | |
427 | 'interesting issue #123', |
|
425 | 'interesting issue #123', | |
428 | """interesting issue <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">PR123</a>"""), |
|
426 | """interesting issue <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">PR123</a>"""), | |
429 | (r'BUG\d{5}', 'https://bar/{repo}/\\1', '\\1', |
|
427 | (r'BUG\d{5}', 'https://bar/{repo}/\\1', '\\1', | |
430 | 'silly me, I did not parenthesize the id, BUG12345.', |
|
428 | 'silly me, I did not parenthesize the id, BUG12345.', | |
431 | """silly me, I did not parenthesize the id, <a class="issue-tracker-link" href="https://bar/repo_name/\\1">BUG12345</a>."""), |
|
429 | """silly me, I did not parenthesize the id, <a class="issue-tracker-link" href="https://bar/repo_name/\\1">BUG12345</a>."""), | |
432 | (r'BUG(\d{5})', 'https://bar/{repo}/', 'BUG\\1', |
|
430 | (r'BUG(\d{5})', 'https://bar/{repo}/', 'BUG\\1', | |
433 | 'silly me, the URL does not contain id, BUG12345.', |
|
431 | 'silly me, the URL does not contain id, BUG12345.', | |
434 | """silly me, the URL does not contain id, <a class="issue-tracker-link" href="https://bar/repo_name/">BUG12345</a>."""), |
|
432 | """silly me, the URL does not contain id, <a class="issue-tracker-link" href="https://bar/repo_name/">BUG12345</a>."""), | |
435 | (r'(PR-\d+)', 'http://foo/{repo}/issue/\\1', '', |
|
433 | (r'(PR-\d+)', 'http://foo/{repo}/issue/\\1', '', | |
436 | 'interesting issue #123, err PR-56', |
|
434 | 'interesting issue #123, err PR-56', | |
437 | """interesting issue #123, err <a class="issue-tracker-link" href="http://foo/repo_name/issue/PR-56">PR-56</a>"""), |
|
435 | """interesting issue #123, err <a class="issue-tracker-link" href="http://foo/repo_name/issue/PR-56">PR-56</a>"""), | |
438 | (r'#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', |
|
436 | (r'#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', | |
439 | "some 'standard' text with apostrophes", |
|
437 | "some 'standard' text with apostrophes", | |
440 | """some 'standard' text with apostrophes"""), |
|
438 | """some 'standard' text with apostrophes"""), | |
441 | (r'#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', |
|
439 | (r'#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', | |
442 | "some 'standard' issue #123", |
|
440 | "some 'standard' issue #123", | |
443 | """some 'standard' issue <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a>"""), |
|
441 | """some 'standard' issue <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a>"""), | |
444 | (r'#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', |
|
442 | (r'#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', | |
445 | 'an issue #123 with extra whitespace', |
|
443 | 'an issue #123 with extra whitespace', | |
446 | """an issue <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> with extra whitespace"""), |
|
444 | """an issue <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> with extra whitespace"""), | |
447 | (r'(?:\s*#)(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', |
|
445 | (r'(?:\s*#)(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', | |
448 | 'an issue #123 with extra whitespace', |
|
446 | 'an issue #123 with extra whitespace', | |
449 | """an issue<a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> with extra whitespace"""), |
|
447 | """an issue<a class="issue-tracker-link" href="http://foo/repo_name/issue/123">#123</a> with extra whitespace"""), | |
450 | # invalid issue pattern |
|
448 | # invalid issue pattern | |
451 | (r'(PR\d+', 'http://foo/{repo}/issue/{id}', '', |
|
449 | (r'(PR\d+', 'http://foo/{repo}/issue/{id}', '', | |
452 | 'PR135', |
|
450 | 'PR135', | |
453 | """PR135"""), |
|
451 | """PR135"""), | |
454 | # other character than # |
|
452 | # other character than # | |
455 | (r'(?:^|(?<=\s))\$(\d+)', 'http://foo/{repo}/issue/\\1', '', |
|
453 | (r'(?:^|(?<=\s))\$(\d+)', 'http://foo/{repo}/issue/\\1', '', | |
456 | 'empty issue_sub $123 and issue$456', |
|
454 | 'empty issue_sub $123 and issue$456', | |
457 | """empty issue_sub <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">$123</a> and """ |
|
455 | """empty issue_sub <a class="issue-tracker-link" href="http://foo/repo_name/issue/123">$123</a> and """ | |
458 | """issue$456"""), |
|
456 | """issue$456"""), | |
459 | # named groups |
|
457 | # named groups | |
460 | (r'(PR|pullrequest|pull request) ?(?P<sitecode>BRU|CPH|BER)-(?P<id>\d+)', r'http://foo/\g<sitecode>/pullrequest/\g<id>/', r'PR-\g<sitecode>-\g<id>', |
|
458 | (r'(PR|pullrequest|pull request) ?(?P<sitecode>BRU|CPH|BER)-(?P<id>\d+)', r'http://foo/\g<sitecode>/pullrequest/\g<id>/', r'PR-\g<sitecode>-\g<id>', | |
461 | 'pullrequest CPH-789 is similar to PRBRU-747', |
|
459 | 'pullrequest CPH-789 is similar to PRBRU-747', | |
462 | """<a class="issue-tracker-link" href="http://foo/CPH/pullrequest/789/">PR-CPH-789</a> is similar to """ |
|
460 | """<a class="issue-tracker-link" href="http://foo/CPH/pullrequest/789/">PR-CPH-789</a> is similar to """ | |
463 | """<a class="issue-tracker-link" href="http://foo/BRU/pullrequest/747/">PR-BRU-747</a>"""), |
|
461 | """<a class="issue-tracker-link" href="http://foo/BRU/pullrequest/747/">PR-BRU-747</a>"""), | |
464 | ]) |
|
462 | ]) | |
465 | def test_urlify_issues(self, issue_pat, issue_server, issue_sub, sample, expected): |
|
463 | def test_urlify_issues(self, issue_pat, issue_server, issue_sub, sample, expected): | |
466 | config_stub = { |
|
464 | config_stub = { | |
467 | 'sqlalchemy.url': 'foo', |
|
465 | 'sqlalchemy.url': 'foo', | |
468 | 'issue_pat': issue_pat, |
|
466 | 'issue_pat': issue_pat, | |
469 | 'issue_server_link': issue_server, |
|
467 | 'issue_server_link': issue_server, | |
470 | 'issue_sub': issue_sub, |
|
468 | 'issue_sub': issue_sub, | |
471 | } |
|
469 | } | |
472 | # force recreation of lazy function |
|
470 | # force recreation of lazy function | |
473 | with mock.patch('kallithea.lib.webutils._urlify_issues_f', None): |
|
471 | with mock.patch('kallithea.lib.webutils._urlify_issues_f', None): | |
474 | with mock.patch('kallithea.CONFIG', config_stub): |
|
472 | with mock.patch('kallithea.CONFIG', config_stub): | |
475 | assert webutils.urlify_text(sample, 'repo_name') == expected |
|
473 | assert webutils.urlify_text(sample, 'repo_name') == expected | |
476 |
|
474 | |||
477 | @base.parametrize('sample,expected', [ |
|
475 | @base.parametrize('sample,expected', [ | |
478 | ('abc X5', 'abc <a class="issue-tracker-link" href="http://main/repo_name/main/5/">#5</a>'), |
|
476 | ('abc X5', 'abc <a class="issue-tracker-link" href="http://main/repo_name/main/5/">#5</a>'), | |
479 | ('abc pullrequest #6 xyz', 'abc <a class="issue-tracker-link" href="http://pr/repo_name/pr/6">PR#6</a> xyz'), |
|
477 | ('abc pullrequest #6 xyz', 'abc <a class="issue-tracker-link" href="http://pr/repo_name/pr/6">PR#6</a> xyz'), | |
480 | ('pull request7 #', '<a class="issue-tracker-link" href="http://pr/repo_name/pr/7">PR#7</a> #'), |
|
478 | ('pull request7 #', '<a class="issue-tracker-link" href="http://pr/repo_name/pr/7">PR#7</a> #'), | |
481 | ('look PR9 and pr #11', 'look <a class="issue-tracker-link" href="http://pr/repo_name/pr/9">PR#9</a> and <a class="issue-tracker-link" href="http://pr/repo_name/pr/11">PR#11</a>'), |
|
479 | ('look PR9 and pr #11', 'look <a class="issue-tracker-link" href="http://pr/repo_name/pr/9">PR#9</a> and <a class="issue-tracker-link" href="http://pr/repo_name/pr/11">PR#11</a>'), | |
482 | ('pullrequest#10 solves issue 9', '<a class="issue-tracker-link" href="http://pr/repo_name/pr/10">PR#10</a> solves <a class="issue-tracker-link" href="http://bug/repo_name/bug/9">bug#9</a>'), |
|
480 | ('pullrequest#10 solves issue 9', '<a class="issue-tracker-link" href="http://pr/repo_name/pr/10">PR#10</a> solves <a class="issue-tracker-link" href="http://bug/repo_name/bug/9">bug#9</a>'), | |
483 | ('issue FAIL67', 'issue <a class="issue-tracker-link" href="http://fail/repo_name/67">FAIL67</a>'), |
|
481 | ('issue FAIL67', 'issue <a class="issue-tracker-link" href="http://fail/repo_name/67">FAIL67</a>'), | |
484 | ('issue FAILMORE89', 'issue FAILMORE89'), # no match because absent prefix |
|
482 | ('issue FAILMORE89', 'issue FAILMORE89'), # no match because absent prefix | |
485 | ]) |
|
483 | ]) | |
486 | def test_urlify_issues_multiple_issue_patterns(self, sample, expected): |
|
484 | def test_urlify_issues_multiple_issue_patterns(self, sample, expected): | |
487 | config_stub = { |
|
485 | config_stub = { | |
488 | 'sqlalchemy.url': r'foo', |
|
486 | 'sqlalchemy.url': r'foo', | |
489 | 'issue_pat': r'X(\d+)', |
|
487 | 'issue_pat': r'X(\d+)', | |
490 | 'issue_server_link': r'http://main/{repo}/main/\1/', |
|
488 | 'issue_server_link': r'http://main/{repo}/main/\1/', | |
491 | 'issue_sub': r'#\1', |
|
489 | 'issue_sub': r'#\1', | |
492 | 'issue_pat_pr': r'(?:pullrequest|pull request|PR|pr) ?#?(\d+)', |
|
490 | 'issue_pat_pr': r'(?:pullrequest|pull request|PR|pr) ?#?(\d+)', | |
493 | 'issue_server_link_pr': r'http://pr/{repo}/pr/\1', |
|
491 | 'issue_server_link_pr': r'http://pr/{repo}/pr/\1', | |
494 | 'issue_sub_pr': r'PR#\1', |
|
492 | 'issue_sub_pr': r'PR#\1', | |
495 | 'issue_pat_bug': r'(?:BUG|bug|issue) ?#?(\d+)', |
|
493 | 'issue_pat_bug': r'(?:BUG|bug|issue) ?#?(\d+)', | |
496 | 'issue_server_link_bug': r'http://bug/{repo}/bug/\1', |
|
494 | 'issue_server_link_bug': r'http://bug/{repo}/bug/\1', | |
497 | 'issue_sub_bug': r'bug#\1', |
|
495 | 'issue_sub_bug': r'bug#\1', | |
498 | 'issue_pat_empty_prefix': r'FAIL(\d+)', |
|
496 | 'issue_pat_empty_prefix': r'FAIL(\d+)', | |
499 | 'issue_server_link_empty_prefix': r'http://fail/{repo}/\1', |
|
497 | 'issue_server_link_empty_prefix': r'http://fail/{repo}/\1', | |
500 | 'issue_sub_empty_prefix': r'', |
|
498 | 'issue_sub_empty_prefix': r'', | |
501 | 'issue_pat_absent_prefix': r'FAILMORE(\d+)', |
|
499 | 'issue_pat_absent_prefix': r'FAILMORE(\d+)', | |
502 | 'issue_server_link_absent_prefix': r'http://failmore/{repo}/\1', |
|
500 | 'issue_server_link_absent_prefix': r'http://failmore/{repo}/\1', | |
503 | } |
|
501 | } | |
504 | # force recreation of lazy function |
|
502 | # force recreation of lazy function | |
505 | with mock.patch('kallithea.lib.webutils._urlify_issues_f', None): |
|
503 | with mock.patch('kallithea.lib.webutils._urlify_issues_f', None): | |
506 | with mock.patch('kallithea.CONFIG', config_stub): |
|
504 | with mock.patch('kallithea.CONFIG', config_stub): | |
507 | assert webutils.urlify_text(sample, 'repo_name') == expected |
|
505 | assert webutils.urlify_text(sample, 'repo_name') == expected | |
508 |
|
506 | |||
509 | @base.parametrize('test,expected', [ |
|
507 | @base.parametrize('test,expected', [ | |
510 | ("", None), |
|
508 | ("", None), | |
511 | ("/_2", None), |
|
509 | ("/_2", None), | |
512 | ("_2", 2), |
|
510 | ("_2", 2), | |
513 | ("_2/", None), |
|
511 | ("_2/", None), | |
514 | ]) |
|
512 | ]) | |
515 | def test_get_permanent_id(self, test, expected): |
|
513 | def test_get_permanent_id(self, test, expected): | |
516 | from kallithea.lib.utils import _get_permanent_id |
|
514 | from kallithea.lib.utils import _get_permanent_id | |
517 | extracted = _get_permanent_id(test) |
|
515 | extracted = _get_permanent_id(test) | |
518 | assert extracted == expected, 'url:%s, got:`%s` expected: `%s`' % (test, base._test, expected) |
|
516 | assert extracted == expected, 'url:%s, got:`%s` expected: `%s`' % (test, base._test, expected) | |
519 |
|
517 | |||
520 | @base.parametrize('test,expected', [ |
|
518 | @base.parametrize('test,expected', [ | |
521 | ("", ""), |
|
519 | ("", ""), | |
522 | ("/", "/"), |
|
520 | ("/", "/"), | |
523 | ("/_ID", '/_ID'), |
|
521 | ("/_ID", '/_ID'), | |
524 | ("ID", "ID"), |
|
522 | ("ID", "ID"), | |
525 | ("_ID", 'NAME'), |
|
523 | ("_ID", 'NAME'), | |
526 | ("_ID/", 'NAME/'), |
|
524 | ("_ID/", 'NAME/'), | |
527 | ("_ID/1/2", 'NAME/1/2'), |
|
525 | ("_ID/1/2", 'NAME/1/2'), | |
528 | ("_IDa", '_IDa'), |
|
526 | ("_IDa", '_IDa'), | |
529 | ]) |
|
527 | ]) | |
530 | def test_fix_repo_id_name(self, test, expected): |
|
528 | def test_fix_repo_id_name(self, test, expected): | |
531 | repo = db.Repository.get_by_repo_name(base.HG_REPO) |
|
529 | repo = db.Repository.get_by_repo_name(base.HG_REPO) | |
532 | test = test.replace('ID', str(repo.repo_id)) |
|
530 | test = test.replace('ID', str(repo.repo_id)) | |
533 | expected = expected.replace('NAME', repo.repo_name).replace('ID', str(repo.repo_id)) |
|
531 | expected = expected.replace('NAME', repo.repo_name).replace('ID', str(repo.repo_id)) | |
534 | from kallithea.lib.utils import fix_repo_id_name |
|
532 | from kallithea.lib.utils import fix_repo_id_name | |
535 | replaced = fix_repo_id_name(test) |
|
533 | replaced = fix_repo_id_name(test) | |
536 | assert replaced == expected, 'url:%s, got:`%s` expected: `%s`' % (test, replaced, expected) |
|
534 | assert replaced == expected, 'url:%s, got:`%s` expected: `%s`' % (test, replaced, expected) | |
537 |
|
535 | |||
538 | @base.parametrize('canonical,test,expected', [ |
|
536 | @base.parametrize('canonical,test,expected', [ | |
539 | ('http://www.example.org/', '/abc/xyz', 'http://www.example.org/abc/xyz'), |
|
537 | ('http://www.example.org/', '/abc/xyz', 'http://www.example.org/abc/xyz'), | |
540 | ('http://www.example.org', '/abc/xyz', 'http://www.example.org/abc/xyz'), |
|
538 | ('http://www.example.org', '/abc/xyz', 'http://www.example.org/abc/xyz'), | |
541 | ('http://www.example.org', '/abc/xyz/', 'http://www.example.org/abc/xyz/'), |
|
539 | ('http://www.example.org', '/abc/xyz/', 'http://www.example.org/abc/xyz/'), | |
542 | ('http://www.example.org', 'abc/xyz/', 'http://www.example.org/abc/xyz/'), |
|
540 | ('http://www.example.org', 'abc/xyz/', 'http://www.example.org/abc/xyz/'), | |
543 | ('http://www.example.org', 'about', 'http://www.example.org/about-page'), |
|
541 | ('http://www.example.org', 'about', 'http://www.example.org/about-page'), | |
544 | ('http://www.example.org/repos/', 'abc/xyz/', 'http://www.example.org/repos/abc/xyz/'), |
|
542 | ('http://www.example.org/repos/', 'abc/xyz/', 'http://www.example.org/repos/abc/xyz/'), | |
545 | ('http://www.example.org/kallithea/repos/', 'abc/xyz/', 'http://www.example.org/kallithea/repos/abc/xyz/'), |
|
543 | ('http://www.example.org/kallithea/repos/', 'abc/xyz/', 'http://www.example.org/kallithea/repos/abc/xyz/'), | |
546 | ]) |
|
544 | ]) | |
547 | def test_canonical_url(self, canonical, test, expected): |
|
545 | def test_canonical_url(self, canonical, test, expected): | |
548 | # setup url(), used by canonical_url |
|
546 | # setup url(), used by canonical_url | |
549 | m = routes.Mapper() |
|
547 | m = routes.Mapper() | |
550 | m.connect('about', '/about-page') |
|
548 | m.connect('about', '/about-page') | |
551 | url = routes.URLGenerator(m, {'HTTP_HOST': 'http_host.example.org'}) |
|
549 | url = routes.URLGenerator(m, {'HTTP_HOST': 'http_host.example.org'}) | |
552 |
|
550 | |||
553 | config_mock = { |
|
551 | config_mock = { | |
554 | 'canonical_url': canonical, |
|
552 | 'canonical_url': canonical, | |
555 | } |
|
553 | } | |
556 |
|
554 | |||
557 | with test_context(self.app): |
|
555 | with test_context(self.app): | |
558 | request.environ['routes.url'] = url |
|
556 | request.environ['routes.url'] = url | |
559 | with mock.patch('kallithea.CONFIG', config_mock): |
|
557 | with mock.patch('kallithea.CONFIG', config_mock): | |
560 | assert webutils.canonical_url(test) == expected |
|
558 | assert webutils.canonical_url(test) == expected | |
561 |
|
559 | |||
562 | @base.parametrize('canonical,expected', [ |
|
560 | @base.parametrize('canonical,expected', [ | |
563 | ('http://www.example.org', 'www.example.org'), |
|
561 | ('http://www.example.org', 'www.example.org'), | |
564 | ('http://www.example.org/repos/', 'www.example.org'), |
|
562 | ('http://www.example.org/repos/', 'www.example.org'), | |
565 | ('http://www.example.org/kallithea/repos/', 'www.example.org'), |
|
563 | ('http://www.example.org/kallithea/repos/', 'www.example.org'), | |
566 | ]) |
|
564 | ]) | |
567 | def test_canonical_hostname(self, canonical, expected): |
|
565 | def test_canonical_hostname(self, canonical, expected): | |
568 | # setup url(), used by canonical_hostname |
|
566 | # setup url(), used by canonical_hostname | |
569 | m = routes.Mapper() |
|
567 | m = routes.Mapper() | |
570 | url = routes.URLGenerator(m, {'HTTP_HOST': 'http_host.example.org'}) |
|
568 | url = routes.URLGenerator(m, {'HTTP_HOST': 'http_host.example.org'}) | |
571 |
|
569 | |||
572 | config_mock = { |
|
570 | config_mock = { | |
573 | 'canonical_url': canonical, |
|
571 | 'canonical_url': canonical, | |
574 | } |
|
572 | } | |
575 |
|
573 | |||
576 | with test_context(self.app): |
|
574 | with test_context(self.app): | |
577 | request.environ['routes.url'] = url |
|
575 | request.environ['routes.url'] = url | |
578 | with mock.patch('kallithea.CONFIG', config_mock): |
|
576 | with mock.patch('kallithea.CONFIG', config_mock): | |
579 | assert webutils.canonical_hostname() == expected |
|
577 | assert webutils.canonical_hostname() == expected |
@@ -1,848 +1,849 b'' | |||||
1 | import datetime |
|
1 | import datetime | |
2 | import os |
|
2 | import os | |
3 | import sys |
|
3 | import sys | |
4 |
|
4 | |||
5 | import mock |
|
5 | import mock | |
6 | import pytest |
|
6 | import pytest | |
7 |
|
7 | |||
8 | from kallithea.lib.vcs.backends.git import GitChangeset, GitRepository |
|
8 | from kallithea.lib.vcs.backends.git import GitChangeset, GitRepository | |
9 | from kallithea.lib.vcs.exceptions import NodeDoesNotExistError, RepositoryError, VCSError |
|
9 | from kallithea.lib.vcs.exceptions import NodeDoesNotExistError, RepositoryError, VCSError | |
10 | from kallithea.lib.vcs.nodes import DirNode, FileNode, NodeKind, NodeState |
|
10 | from kallithea.lib.vcs.nodes import DirNode, FileNode, NodeKind, NodeState | |
11 | from kallithea.model.scm import ScmModel |
|
11 | from kallithea.model.scm import ScmModel | |
12 | from kallithea.tests.vcs.base import _BackendTestMixin |
|
12 | from kallithea.tests.vcs.base import _BackendTestMixin | |
13 | from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_GIT_REPO_CLONE, TESTS_TMP_PATH, get_new_dir |
|
13 | from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_GIT_REPO_CLONE, TESTS_TMP_PATH, get_new_dir | |
14 |
|
14 | |||
15 |
|
15 | |||
16 | class TestGitRepository(object): |
|
16 | class TestGitRepository(object): | |
17 |
|
17 | |||
18 | def __check_for_existing_repo(self): |
|
18 | def __check_for_existing_repo(self): | |
19 | if os.path.exists(TEST_GIT_REPO_CLONE): |
|
19 | if os.path.exists(TEST_GIT_REPO_CLONE): | |
20 | pytest.fail('Cannot test git clone repo as location %s already ' |
|
20 | pytest.fail('Cannot test git clone repo as location %s already ' | |
21 | 'exists. You should manually remove it first.' |
|
21 | 'exists. You should manually remove it first.' | |
22 | % TEST_GIT_REPO_CLONE) |
|
22 | % TEST_GIT_REPO_CLONE) | |
23 |
|
23 | |||
24 | def setup_method(self): |
|
24 | def setup_method(self): | |
25 | self.repo = GitRepository(TEST_GIT_REPO) |
|
25 | self.repo = GitRepository(TEST_GIT_REPO) | |
26 |
|
26 | |||
27 | def test_wrong_repo_path(self): |
|
27 | def test_wrong_repo_path(self): | |
28 | wrong_repo_path = os.path.join(TESTS_TMP_PATH, 'errorrepo') |
|
28 | wrong_repo_path = os.path.join(TESTS_TMP_PATH, 'errorrepo') | |
29 | with pytest.raises(RepositoryError): |
|
29 | with pytest.raises(RepositoryError): | |
30 | GitRepository(wrong_repo_path) |
|
30 | GitRepository(wrong_repo_path) | |
31 |
|
31 | |||
32 | def test_git_cmd_injection(self): |
|
32 | def test_git_cmd_injection(self): | |
33 | repo_inject_path = 'file:/%s; echo "Cake";' % TEST_GIT_REPO |
|
33 | repo_inject_path = 'file:/%s; echo "Cake";' % TEST_GIT_REPO | |
34 | with pytest.raises(RepositoryError): |
|
34 | with pytest.raises(RepositoryError): | |
35 | # Should fail because URL will contain the parts after ; too |
|
35 | # Should fail because URL will contain the parts after ; too | |
36 | GitRepository(get_new_dir('injection-repo'), src_url=repo_inject_path, update_after_clone=True, create=True) |
|
36 | GitRepository(get_new_dir('injection-repo'), src_url=repo_inject_path, update_after_clone=True, create=True) | |
37 |
|
37 | |||
38 | with pytest.raises(RepositoryError): |
|
38 | with pytest.raises(RepositoryError): | |
39 | # Should fail on direct clone call, which as of this writing does not happen outside of class |
|
39 | # Should fail on direct clone call, which as of this writing does not happen outside of class | |
40 | clone_fail_repo = GitRepository(get_new_dir('injection-repo'), create=True) |
|
40 | clone_fail_repo = GitRepository(get_new_dir('injection-repo'), create=True) | |
41 | clone_fail_repo.clone(repo_inject_path, update_after_clone=True,) |
|
41 | clone_fail_repo.clone(repo_inject_path, update_after_clone=True,) | |
42 |
|
42 | |||
43 | # Verify correct quoting of evil characters that should work on posix file systems |
|
43 | # Verify correct quoting of evil characters that should work on posix file systems | |
44 | if sys.platform == 'win32': |
|
44 | if sys.platform == 'win32': | |
45 | # windows does not allow '"' in dir names |
|
45 | # windows does not allow '"' in dir names | |
46 | # and some versions of the git client don't like ` and ' |
|
46 | # and some versions of the git client don't like ` and ' | |
47 | tricky_path = get_new_dir("tricky-path-repo-$") |
|
47 | tricky_path = get_new_dir("tricky-path-repo-$") | |
48 | else: |
|
48 | else: | |
49 | tricky_path = get_new_dir("tricky-path-repo-$'\"`") |
|
49 | tricky_path = get_new_dir("tricky-path-repo-$'\"`") | |
50 | successfully_cloned = GitRepository(tricky_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True) |
|
50 | successfully_cloned = GitRepository(tricky_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True) | |
51 | # Repo should have been created |
|
51 | # Repo should have been created | |
52 | assert not successfully_cloned._repo.bare |
|
52 | assert not successfully_cloned._repo.bare | |
53 |
|
53 | |||
54 | if sys.platform == 'win32': |
|
54 | if sys.platform == 'win32': | |
55 | # windows does not allow '"' in dir names |
|
55 | # windows does not allow '"' in dir names | |
56 | # and some versions of the git client don't like ` and ' |
|
56 | # and some versions of the git client don't like ` and ' | |
57 | tricky_path_2 = get_new_dir("tricky-path-2-repo-$") |
|
57 | tricky_path_2 = get_new_dir("tricky-path-2-repo-$") | |
58 | else: |
|
58 | else: | |
59 | tricky_path_2 = get_new_dir("tricky-path-2-repo-$'\"`") |
|
59 | tricky_path_2 = get_new_dir("tricky-path-2-repo-$'\"`") | |
60 | successfully_cloned2 = GitRepository(tricky_path_2, src_url=tricky_path, bare=True, create=True) |
|
60 | successfully_cloned2 = GitRepository(tricky_path_2, src_url=tricky_path, bare=True, create=True) | |
61 | # Repo should have been created and thus used correct quoting for clone |
|
61 | # Repo should have been created and thus used correct quoting for clone | |
62 | assert successfully_cloned2._repo.bare |
|
62 | assert successfully_cloned2._repo.bare | |
63 |
|
63 | |||
64 | # Should pass because URL has been properly quoted |
|
64 | # Should pass because URL has been properly quoted | |
65 | successfully_cloned.pull(tricky_path_2) |
|
65 | successfully_cloned.pull(tricky_path_2) | |
66 | successfully_cloned2.fetch(tricky_path) |
|
66 | successfully_cloned2.fetch(tricky_path) | |
67 |
|
67 | |||
68 | def test_repo_create_with_spaces_in_path(self): |
|
68 | def test_repo_create_with_spaces_in_path(self): | |
69 | repo_path = get_new_dir("path with spaces") |
|
69 | repo_path = get_new_dir("path with spaces") | |
70 | repo = GitRepository(repo_path, src_url=None, bare=True, create=True) |
|
70 | repo = GitRepository(repo_path, src_url=None, bare=True, create=True) | |
71 | # Repo should have been created |
|
71 | # Repo should have been created | |
72 | assert repo._repo.bare |
|
72 | assert repo._repo.bare | |
73 |
|
73 | |||
74 | def test_repo_clone(self): |
|
74 | def test_repo_clone(self): | |
75 | self.__check_for_existing_repo() |
|
75 | self.__check_for_existing_repo() | |
76 | repo = GitRepository(TEST_GIT_REPO) |
|
76 | repo = GitRepository(TEST_GIT_REPO) | |
77 | repo_clone = GitRepository(TEST_GIT_REPO_CLONE, |
|
77 | repo_clone = GitRepository(TEST_GIT_REPO_CLONE, | |
78 | src_url=TEST_GIT_REPO, create=True, update_after_clone=True) |
|
78 | src_url=TEST_GIT_REPO, create=True, update_after_clone=True) | |
79 | assert len(repo.revisions) == len(repo_clone.revisions) |
|
79 | assert len(repo.revisions) == len(repo_clone.revisions) | |
80 | # Checking hashes of changesets should be enough |
|
80 | # Checking hashes of changesets should be enough | |
81 | for changeset in repo.get_changesets(): |
|
81 | for changeset in repo.get_changesets(): | |
82 | raw_id = changeset.raw_id |
|
82 | raw_id = changeset.raw_id | |
83 | assert raw_id == repo_clone.get_changeset(raw_id).raw_id |
|
83 | assert raw_id == repo_clone.get_changeset(raw_id).raw_id | |
84 |
|
84 | |||
85 | def test_repo_clone_with_spaces_in_path(self): |
|
85 | def test_repo_clone_with_spaces_in_path(self): | |
86 | repo_path = get_new_dir("path with spaces") |
|
86 | repo_path = get_new_dir("path with spaces") | |
87 | successfully_cloned = GitRepository(repo_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True) |
|
87 | successfully_cloned = GitRepository(repo_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True) | |
88 | # Repo should have been created |
|
88 | # Repo should have been created | |
89 | assert not successfully_cloned._repo.bare |
|
89 | assert not successfully_cloned._repo.bare | |
90 |
|
90 | |||
91 | successfully_cloned.pull(TEST_GIT_REPO) |
|
91 | successfully_cloned.pull(TEST_GIT_REPO) | |
92 | self.repo.fetch(repo_path) |
|
92 | self.repo.fetch(repo_path) | |
93 |
|
93 | |||
94 | def test_repo_clone_without_create(self): |
|
94 | def test_repo_clone_without_create(self): | |
95 | with pytest.raises(RepositoryError): |
|
95 | with pytest.raises(RepositoryError): | |
96 | GitRepository(TEST_GIT_REPO_CLONE + '_wo_create', src_url=TEST_GIT_REPO) |
|
96 | GitRepository(TEST_GIT_REPO_CLONE + '_wo_create', src_url=TEST_GIT_REPO) | |
97 |
|
97 | |||
98 | def test_repo_clone_with_update(self): |
|
98 | def test_repo_clone_with_update(self): | |
99 | repo = GitRepository(TEST_GIT_REPO) |
|
99 | repo = GitRepository(TEST_GIT_REPO) | |
100 | clone_path = TEST_GIT_REPO_CLONE + '_with_update' |
|
100 | clone_path = TEST_GIT_REPO_CLONE + '_with_update' | |
101 | repo_clone = GitRepository(clone_path, |
|
101 | repo_clone = GitRepository(clone_path, | |
102 | create=True, src_url=TEST_GIT_REPO, update_after_clone=True) |
|
102 | create=True, src_url=TEST_GIT_REPO, update_after_clone=True) | |
103 | assert len(repo.revisions) == len(repo_clone.revisions) |
|
103 | assert len(repo.revisions) == len(repo_clone.revisions) | |
104 |
|
104 | |||
105 | # check if current workdir was updated |
|
105 | # check if current workdir was updated | |
106 | fpath = os.path.join(clone_path, 'MANIFEST.in') |
|
106 | fpath = os.path.join(clone_path, 'MANIFEST.in') | |
107 | assert os.path.isfile(fpath) == True, 'Repo was cloned and updated but file %s could not be found' % fpath |
|
107 | assert os.path.isfile(fpath) == True, 'Repo was cloned and updated but file %s could not be found' % fpath | |
108 |
|
108 | |||
109 | def test_repo_clone_without_update(self): |
|
109 | def test_repo_clone_without_update(self): | |
110 | repo = GitRepository(TEST_GIT_REPO) |
|
110 | repo = GitRepository(TEST_GIT_REPO) | |
111 | clone_path = TEST_GIT_REPO_CLONE + '_without_update' |
|
111 | clone_path = TEST_GIT_REPO_CLONE + '_without_update' | |
112 | repo_clone = GitRepository(clone_path, |
|
112 | repo_clone = GitRepository(clone_path, | |
113 | create=True, src_url=TEST_GIT_REPO, update_after_clone=False) |
|
113 | create=True, src_url=TEST_GIT_REPO, update_after_clone=False) | |
114 | assert len(repo.revisions) == len(repo_clone.revisions) |
|
114 | assert len(repo.revisions) == len(repo_clone.revisions) | |
115 | # check if current workdir was *NOT* updated |
|
115 | # check if current workdir was *NOT* updated | |
116 | fpath = os.path.join(clone_path, 'MANIFEST.in') |
|
116 | fpath = os.path.join(clone_path, 'MANIFEST.in') | |
117 | # Make sure it's not bare repo |
|
117 | # Make sure it's not bare repo | |
118 | assert not repo_clone._repo.bare |
|
118 | assert not repo_clone._repo.bare | |
119 | assert os.path.isfile(fpath) == False, 'Repo was cloned and updated but file %s was found' % fpath |
|
119 | assert os.path.isfile(fpath) == False, 'Repo was cloned and updated but file %s was found' % fpath | |
120 |
|
120 | |||
121 | def test_repo_clone_into_bare_repo(self): |
|
121 | def test_repo_clone_into_bare_repo(self): | |
122 | repo = GitRepository(TEST_GIT_REPO) |
|
122 | repo = GitRepository(TEST_GIT_REPO) | |
123 | clone_path = TEST_GIT_REPO_CLONE + '_bare.git' |
|
123 | clone_path = TEST_GIT_REPO_CLONE + '_bare.git' | |
124 | repo_clone = GitRepository(clone_path, create=True, |
|
124 | repo_clone = GitRepository(clone_path, create=True, | |
125 | src_url=repo.path, bare=True) |
|
125 | src_url=repo.path, bare=True) | |
126 | assert repo_clone._repo.bare |
|
126 | assert repo_clone._repo.bare | |
127 |
|
127 | |||
128 | def test_create_repo_is_not_bare_by_default(self): |
|
128 | def test_create_repo_is_not_bare_by_default(self): | |
129 | repo = GitRepository(get_new_dir('not-bare-by-default'), create=True) |
|
129 | repo = GitRepository(get_new_dir('not-bare-by-default'), create=True) | |
130 | assert not repo._repo.bare |
|
130 | assert not repo._repo.bare | |
131 |
|
131 | |||
132 | def test_create_bare_repo(self): |
|
132 | def test_create_bare_repo(self): | |
133 | repo = GitRepository(get_new_dir('bare-repo'), create=True, bare=True) |
|
133 | repo = GitRepository(get_new_dir('bare-repo'), create=True, bare=True) | |
134 | assert repo._repo.bare |
|
134 | assert repo._repo.bare | |
135 |
|
135 | |||
136 | def test_revisions(self): |
|
136 | def test_revisions(self): | |
137 | # there are 112 revisions (by now) |
|
137 | # there are 112 revisions (by now) | |
138 | # so we can assume they would be available from now on |
|
138 | # so we can assume they would be available from now on | |
139 | subset = set([ |
|
139 | subset = set([ | |
140 | 'c1214f7e79e02fc37156ff215cd71275450cffc3', |
|
140 | 'c1214f7e79e02fc37156ff215cd71275450cffc3', | |
141 | '38b5fe81f109cb111f549bfe9bb6b267e10bc557', |
|
141 | '38b5fe81f109cb111f549bfe9bb6b267e10bc557', | |
142 | 'fa6600f6848800641328adbf7811fd2372c02ab2', |
|
142 | 'fa6600f6848800641328adbf7811fd2372c02ab2', | |
143 | '102607b09cdd60e2793929c4f90478be29f85a17', |
|
143 | '102607b09cdd60e2793929c4f90478be29f85a17', | |
144 | '49d3fd156b6f7db46313fac355dca1a0b94a0017', |
|
144 | '49d3fd156b6f7db46313fac355dca1a0b94a0017', | |
145 | '2d1028c054665b962fa3d307adfc923ddd528038', |
|
145 | '2d1028c054665b962fa3d307adfc923ddd528038', | |
146 | 'd7e0d30fbcae12c90680eb095a4f5f02505ce501', |
|
146 | 'd7e0d30fbcae12c90680eb095a4f5f02505ce501', | |
147 | 'ff7ca51e58c505fec0dd2491de52c622bb7a806b', |
|
147 | 'ff7ca51e58c505fec0dd2491de52c622bb7a806b', | |
148 | 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f', |
|
148 | 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f', | |
149 | '8430a588b43b5d6da365400117c89400326e7992', |
|
149 | '8430a588b43b5d6da365400117c89400326e7992', | |
150 | 'd955cd312c17b02143c04fa1099a352b04368118', |
|
150 | 'd955cd312c17b02143c04fa1099a352b04368118', | |
151 | 'f67b87e5c629c2ee0ba58f85197e423ff28d735b', |
|
151 | 'f67b87e5c629c2ee0ba58f85197e423ff28d735b', | |
152 | 'add63e382e4aabc9e1afdc4bdc24506c269b7618', |
|
152 | 'add63e382e4aabc9e1afdc4bdc24506c269b7618', | |
153 | 'f298fe1189f1b69779a4423f40b48edf92a703fc', |
|
153 | 'f298fe1189f1b69779a4423f40b48edf92a703fc', | |
154 | 'bd9b619eb41994cac43d67cf4ccc8399c1125808', |
|
154 | 'bd9b619eb41994cac43d67cf4ccc8399c1125808', | |
155 | '6e125e7c890379446e98980d8ed60fba87d0f6d1', |
|
155 | '6e125e7c890379446e98980d8ed60fba87d0f6d1', | |
156 | 'd4a54db9f745dfeba6933bf5b1e79e15d0af20bd', |
|
156 | 'd4a54db9f745dfeba6933bf5b1e79e15d0af20bd', | |
157 | '0b05e4ed56c802098dfc813cbe779b2f49e92500', |
|
157 | '0b05e4ed56c802098dfc813cbe779b2f49e92500', | |
158 | '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e', |
|
158 | '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e', | |
159 | '45223f8f114c64bf4d6f853e3c35a369a6305520', |
|
159 | '45223f8f114c64bf4d6f853e3c35a369a6305520', | |
160 | 'ca1eb7957a54bce53b12d1a51b13452f95bc7c7e', |
|
160 | 'ca1eb7957a54bce53b12d1a51b13452f95bc7c7e', | |
161 | 'f5ea29fc42ef67a2a5a7aecff10e1566699acd68', |
|
161 | 'f5ea29fc42ef67a2a5a7aecff10e1566699acd68', | |
162 | '27d48942240f5b91dfda77accd2caac94708cc7d', |
|
162 | '27d48942240f5b91dfda77accd2caac94708cc7d', | |
163 | '622f0eb0bafd619d2560c26f80f09e3b0b0d78af', |
|
163 | '622f0eb0bafd619d2560c26f80f09e3b0b0d78af', | |
164 | 'e686b958768ee96af8029fe19c6050b1a8dd3b2b']) |
|
164 | 'e686b958768ee96af8029fe19c6050b1a8dd3b2b']) | |
165 | assert subset.issubset(set(self.repo.revisions)) |
|
165 | assert subset.issubset(set(self.repo.revisions)) | |
166 |
|
166 | |||
167 | def test_slicing(self): |
|
167 | def test_slicing(self): | |
168 | # 4 1 5 10 95 |
|
168 | # 4 1 5 10 95 | |
169 | for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5), |
|
169 | for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5), | |
170 | (10, 20, 10), (5, 100, 95)]: |
|
170 | (10, 20, 10), (5, 100, 95)]: | |
171 | revs = list(self.repo[sfrom:sto]) |
|
171 | revs = list(self.repo[sfrom:sto]) | |
172 | assert len(revs) == size |
|
172 | assert len(revs) == size | |
173 | assert revs[0] == self.repo.get_changeset(sfrom) |
|
173 | assert revs[0] == self.repo.get_changeset(sfrom) | |
174 | assert revs[-1] == self.repo.get_changeset(sto - 1) |
|
174 | assert revs[-1] == self.repo.get_changeset(sto - 1) | |
175 |
|
175 | |||
176 | def test_branches(self): |
|
176 | def test_branches(self): | |
177 | # TODO: Need more tests here |
|
177 | # TODO: Need more tests here | |
178 | # Removed (those are 'remotes' branches for cloned repo) |
|
178 | # Removed (those are 'remotes' branches for cloned repo) | |
179 | #assert 'master' in self.repo.branches |
|
179 | #assert 'master' in self.repo.branches | |
180 | #assert 'gittree' in self.repo.branches |
|
180 | #assert 'gittree' in self.repo.branches | |
181 | #assert 'web-branch' in self.repo.branches |
|
181 | #assert 'web-branch' in self.repo.branches | |
182 | for name, id in self.repo.branches.items(): |
|
182 | for name, id in self.repo.branches.items(): | |
183 | assert isinstance(self.repo.get_changeset(id), GitChangeset) |
|
183 | assert isinstance(self.repo.get_changeset(id), GitChangeset) | |
184 |
|
184 | |||
185 | def test_tags(self): |
|
185 | def test_tags(self): | |
186 | # TODO: Need more tests here |
|
186 | # TODO: Need more tests here | |
187 | assert 'v0.1.1' in self.repo.tags |
|
187 | assert 'v0.1.1' in self.repo.tags | |
188 | assert 'v0.1.2' in self.repo.tags |
|
188 | assert 'v0.1.2' in self.repo.tags | |
189 | for name, id in self.repo.tags.items(): |
|
189 | for name, id in self.repo.tags.items(): | |
190 | assert isinstance(self.repo.get_changeset(id), GitChangeset) |
|
190 | assert isinstance(self.repo.get_changeset(id), GitChangeset) | |
191 |
|
191 | |||
192 | def _test_single_changeset_cache(self, revision): |
|
192 | def _test_single_changeset_cache(self, revision): | |
193 | chset = self.repo.get_changeset(revision) |
|
193 | chset = self.repo.get_changeset(revision) | |
194 | assert revision in self.repo.changesets |
|
194 | assert revision in self.repo.changesets | |
195 | assert chset is self.repo.changesets[revision] |
|
195 | assert chset is self.repo.changesets[revision] | |
196 |
|
196 | |||
197 | def test_initial_changeset(self): |
|
197 | def test_initial_changeset(self): | |
198 | id = self.repo.revisions[0] |
|
198 | id = self.repo.revisions[0] | |
199 | init_chset = self.repo.get_changeset(id) |
|
199 | init_chset = self.repo.get_changeset(id) | |
200 | assert init_chset.message == 'initial import\n' |
|
200 | assert init_chset.message == 'initial import\n' | |
201 | assert init_chset.author == 'Marcin Kuzminski <marcin@python-blog.com>' |
|
201 | assert init_chset.author == 'Marcin Kuzminski <marcin@python-blog.com>' | |
202 | for path in ('vcs/__init__.py', |
|
202 | for path in ('vcs/__init__.py', | |
203 | 'vcs/backends/BaseRepository.py', |
|
203 | 'vcs/backends/BaseRepository.py', | |
204 | 'vcs/backends/__init__.py'): |
|
204 | 'vcs/backends/__init__.py'): | |
205 | assert isinstance(init_chset.get_node(path), FileNode) |
|
205 | assert isinstance(init_chset.get_node(path), FileNode) | |
206 | for path in ('', 'vcs', 'vcs/backends'): |
|
206 | for path in ('', 'vcs', 'vcs/backends'): | |
207 | assert isinstance(init_chset.get_node(path), DirNode) |
|
207 | assert isinstance(init_chset.get_node(path), DirNode) | |
208 |
|
208 | |||
209 | with pytest.raises(NodeDoesNotExistError): |
|
209 | with pytest.raises(NodeDoesNotExistError): | |
210 | init_chset.get_node(path='foobar') |
|
210 | init_chset.get_node(path='foobar') | |
211 |
|
211 | |||
212 | node = init_chset.get_node('vcs/') |
|
212 | node = init_chset.get_node('vcs/') | |
213 | assert hasattr(node, 'kind') |
|
213 | assert hasattr(node, 'kind') | |
214 | assert node.kind == NodeKind.DIR |
|
214 | assert node.kind == NodeKind.DIR | |
215 |
|
215 | |||
216 | node = init_chset.get_node('vcs') |
|
216 | node = init_chset.get_node('vcs') | |
217 | assert hasattr(node, 'kind') |
|
217 | assert hasattr(node, 'kind') | |
218 | assert node.kind == NodeKind.DIR |
|
218 | assert node.kind == NodeKind.DIR | |
219 |
|
219 | |||
220 | node = init_chset.get_node('vcs/__init__.py') |
|
220 | node = init_chset.get_node('vcs/__init__.py') | |
221 | assert hasattr(node, 'kind') |
|
221 | assert hasattr(node, 'kind') | |
222 | assert node.kind == NodeKind.FILE |
|
222 | assert node.kind == NodeKind.FILE | |
223 |
|
223 | |||
224 | def test_not_existing_changeset(self): |
|
224 | def test_not_existing_changeset(self): | |
225 | with pytest.raises(RepositoryError): |
|
225 | with pytest.raises(RepositoryError): | |
226 | self.repo.get_changeset('f' * 40) |
|
226 | self.repo.get_changeset('f' * 40) | |
227 |
|
227 | |||
228 | def test_changeset10(self): |
|
228 | def test_changeset10(self): | |
229 |
|
229 | |||
230 | chset10 = self.repo.get_changeset(self.repo.revisions[9]) |
|
230 | chset10 = self.repo.get_changeset(self.repo.revisions[9]) | |
231 | readme = b"""=== |
|
231 | readme = b"""=== | |
232 | VCS |
|
232 | VCS | |
233 | === |
|
233 | === | |
234 |
|
234 | |||
235 | Various Version Control System management abstraction layer for Python. |
|
235 | Various Version Control System management abstraction layer for Python. | |
236 |
|
236 | |||
237 | Introduction |
|
237 | Introduction | |
238 | ------------ |
|
238 | ------------ | |
239 |
|
239 | |||
240 | TODO: To be written... |
|
240 | TODO: To be written... | |
241 |
|
241 | |||
242 | """ |
|
242 | """ | |
243 | node = chset10.get_node('README.rst') |
|
243 | node = chset10.get_node('README.rst') | |
244 | assert node.kind == NodeKind.FILE |
|
244 | assert node.kind == NodeKind.FILE | |
245 | assert node.content == readme |
|
245 | assert node.content == readme | |
246 |
|
246 | |||
247 |
|
247 | |||
248 | class TestGitChangeset(object): |
|
248 | class TestGitChangeset(object): | |
249 |
|
249 | |||
250 | def setup_method(self): |
|
250 | def setup_method(self): | |
251 | self.repo = GitRepository(TEST_GIT_REPO) |
|
251 | self.repo = GitRepository(TEST_GIT_REPO) | |
252 |
|
252 | |||
253 | def test_default_changeset(self): |
|
253 | def test_default_changeset(self): | |
254 | tip = self.repo.get_changeset() |
|
254 | tip = self.repo.get_changeset() | |
255 | assert tip == self.repo.get_changeset(None) |
|
255 | assert tip == self.repo.get_changeset(None) | |
256 | assert tip == self.repo.get_changeset('tip') |
|
256 | assert tip == self.repo.get_changeset('tip') | |
257 |
|
257 | |||
258 | def test_root_node(self): |
|
258 | def test_root_node(self): | |
259 | tip = self.repo.get_changeset() |
|
259 | tip = self.repo.get_changeset() | |
260 | assert tip.root is tip.get_node('') |
|
260 | assert tip.root is tip.get_node('') | |
261 |
|
261 | |||
262 | def test_lazy_fetch(self): |
|
262 | def test_lazy_fetch(self): | |
263 | """ |
|
263 | """ | |
264 | Test if changeset's nodes expands and are cached as we walk through |
|
264 | Test if changeset's nodes expands and are cached as we walk through | |
265 | the revision. This test is somewhat hard to write as order of tests |
|
265 | the revision. This test is somewhat hard to write as order of tests | |
266 | is a key here. Written by running command after command in a shell. |
|
266 | is a key here. Written by running command after command in a shell. | |
267 | """ |
|
267 | """ | |
268 | commit_id = '2a13f185e4525f9d4b59882791a2d397b90d5ddc' |
|
268 | commit_id = '2a13f185e4525f9d4b59882791a2d397b90d5ddc' | |
269 | assert commit_id in self.repo.revisions |
|
269 | assert commit_id in self.repo.revisions | |
270 | chset = self.repo.get_changeset(commit_id) |
|
270 | chset = self.repo.get_changeset(commit_id) | |
271 | assert len(chset.nodes) == 0 |
|
271 | assert len(chset.nodes) == 0 | |
272 | root = chset.root |
|
272 | root = chset.root | |
273 | assert len(chset.nodes) == 1 |
|
273 | assert len(chset.nodes) == 1 | |
274 | assert len(root.nodes) == 8 |
|
274 | assert len(root.nodes) == 8 | |
275 | # accessing root.nodes updates chset.nodes |
|
275 | # accessing root.nodes updates chset.nodes | |
276 | assert len(chset.nodes) == 9 |
|
276 | assert len(chset.nodes) == 9 | |
277 |
|
277 | |||
278 | docs = root.get_node('docs') |
|
278 | docs = root.get_node('docs') | |
279 | # we haven't yet accessed anything new as docs dir was already cached |
|
279 | # we haven't yet accessed anything new as docs dir was already cached | |
280 | assert len(chset.nodes) == 9 |
|
280 | assert len(chset.nodes) == 9 | |
281 | assert len(docs.nodes) == 8 |
|
281 | assert len(docs.nodes) == 8 | |
282 | # accessing docs.nodes updates chset.nodes |
|
282 | # accessing docs.nodes updates chset.nodes | |
283 | assert len(chset.nodes) == 17 |
|
283 | assert len(chset.nodes) == 17 | |
284 |
|
284 | |||
285 | assert docs is chset.get_node('docs') |
|
285 | assert docs is chset.get_node('docs') | |
286 | assert docs is root.nodes[0] |
|
286 | assert docs is root.nodes[0] | |
287 | assert docs is root.dirs[0] |
|
287 | assert docs is root.dirs[0] | |
288 | assert docs is chset.get_node('docs') |
|
288 | assert docs is chset.get_node('docs') | |
289 |
|
289 | |||
290 | def test_nodes_with_changeset(self): |
|
290 | def test_nodes_with_changeset(self): | |
291 | commit_id = '2a13f185e4525f9d4b59882791a2d397b90d5ddc' |
|
291 | commit_id = '2a13f185e4525f9d4b59882791a2d397b90d5ddc' | |
292 | chset = self.repo.get_changeset(commit_id) |
|
292 | chset = self.repo.get_changeset(commit_id) | |
293 | root = chset.root |
|
293 | root = chset.root | |
294 | docs = root.get_node('docs') |
|
294 | docs = root.get_node('docs') | |
295 | assert docs is chset.get_node('docs') |
|
295 | assert docs is chset.get_node('docs') | |
296 | api = docs.get_node('api') |
|
296 | api = docs.get_node('api') | |
297 | assert api is chset.get_node('docs/api') |
|
297 | assert api is chset.get_node('docs/api') | |
298 | index = api.get_node('index.rst') |
|
298 | index = api.get_node('index.rst') | |
299 | assert index is chset.get_node('docs/api/index.rst') |
|
299 | assert index is chset.get_node('docs/api/index.rst') | |
300 | assert index is chset.get_node('docs') \ |
|
300 | assert index is chset.get_node('docs') \ | |
301 | .get_node('api') \ |
|
301 | .get_node('api') \ | |
302 | .get_node('index.rst') |
|
302 | .get_node('index.rst') | |
303 |
|
303 | |||
304 | def test_branch_and_tags(self): |
|
304 | def test_branch_and_tags(self): | |
305 | # Those tests seem to show wrong results: |
|
305 | # Those tests seem to show wrong results: | |
306 | # in Git, only heads have a branch - most changesets don't |
|
306 | # in Git, only heads have a branch - most changesets don't | |
307 | rev0 = self.repo.revisions[0] |
|
307 | rev0 = self.repo.revisions[0] | |
308 | chset0 = self.repo.get_changeset(rev0) |
|
308 | chset0 = self.repo.get_changeset(rev0) | |
309 | assert chset0.branch is None # should be 'master'? |
|
309 | assert chset0.branch is None # should be 'master'? | |
310 | assert chset0.branches == [] # should be 'master'? |
|
310 | assert chset0.branches == [] # should be 'master'? | |
311 | assert chset0.tags == [] |
|
311 | assert chset0.tags == [] | |
312 |
|
312 | |||
313 | rev10 = self.repo.revisions[10] |
|
313 | rev10 = self.repo.revisions[10] | |
314 | chset10 = self.repo.get_changeset(rev10) |
|
314 | chset10 = self.repo.get_changeset(rev10) | |
315 | assert chset10.branch is None # should be 'master'? |
|
315 | assert chset10.branch is None # should be 'master'? | |
316 | assert chset10.branches == [] # should be 'master'? |
|
316 | assert chset10.branches == [] # should be 'master'? | |
317 | assert chset10.tags == [] |
|
317 | assert chset10.tags == [] | |
318 |
|
318 | |||
319 | rev44 = self.repo.revisions[44] |
|
319 | rev44 = self.repo.revisions[44] | |
320 | chset44 = self.repo.get_changeset(rev44) |
|
320 | chset44 = self.repo.get_changeset(rev44) | |
321 | assert chset44.branch is None # should be 'web-branch'? |
|
321 | assert chset44.branch is None # should be 'web-branch'? | |
322 | assert chset44.branches == [] # should be 'web-branch'? |
|
322 | assert chset44.branches == [] # should be 'web-branch'? | |
323 |
|
323 | |||
324 | tip = self.repo.get_changeset('tip') |
|
324 | tip = self.repo.get_changeset('tip') | |
325 | assert 'tip' not in tip.tags # it should be? |
|
325 | assert 'tip' not in tip.tags # it should be? | |
326 | assert not tip.tags # how it is! |
|
326 | assert not tip.tags # how it is! | |
327 |
|
327 | |||
328 | def _test_slices(self, limit, offset): |
|
328 | def _test_slices(self, limit, offset): | |
329 | count = self.repo.count() |
|
329 | count = self.repo.count() | |
330 | changesets = self.repo.get_changesets(limit=limit, offset=offset) |
|
330 | changesets = self.repo.get_changesets(limit=limit, offset=offset) | |
331 | idx = 0 |
|
331 | idx = 0 | |
332 | for changeset in changesets: |
|
332 | for changeset in changesets: | |
333 | rev = offset + idx |
|
333 | rev = offset + idx | |
334 | idx += 1 |
|
334 | idx += 1 | |
335 | rev_id = self.repo.revisions[rev] |
|
335 | rev_id = self.repo.revisions[rev] | |
336 | if idx > limit: |
|
336 | if idx > limit: | |
337 | pytest.fail("Exceeded limit already (getting revision %s, " |
|
337 | pytest.fail("Exceeded limit already (getting revision %s, " | |
338 | "there are %s total revisions, offset=%s, limit=%s)" |
|
338 | "there are %s total revisions, offset=%s, limit=%s)" | |
339 | % (rev_id, count, offset, limit)) |
|
339 | % (rev_id, count, offset, limit)) | |
340 | assert changeset == self.repo.get_changeset(rev_id) |
|
340 | assert changeset == self.repo.get_changeset(rev_id) | |
341 | result = list(self.repo.get_changesets(limit=limit, offset=offset)) |
|
341 | result = list(self.repo.get_changesets(limit=limit, offset=offset)) | |
342 | start = offset |
|
342 | start = offset | |
343 | end = limit and offset + limit or None |
|
343 | end = limit and offset + limit or None | |
344 | sliced = list(self.repo[start:end]) |
|
344 | sliced = list(self.repo[start:end]) | |
345 | pytest.assertEqual(result, sliced, |
|
345 | pytest.assertEqual(result, sliced, | |
346 | msg="Comparison failed for limit=%s, offset=%s" |
|
346 | msg="Comparison failed for limit=%s, offset=%s" | |
347 | "(get_changeset returned: %s and sliced: %s" |
|
347 | "(get_changeset returned: %s and sliced: %s" | |
348 | % (limit, offset, result, sliced)) |
|
348 | % (limit, offset, result, sliced)) | |
349 |
|
349 | |||
350 | def _test_file_size(self, revision, path, size): |
|
350 | def _test_file_size(self, revision, path, size): | |
351 | node = self.repo.get_changeset(revision).get_node(path) |
|
351 | node = self.repo.get_changeset(revision).get_node(path) | |
352 | assert node.is_file() |
|
352 | assert node.is_file() | |
353 | assert node.size == size |
|
353 | assert node.size == size | |
354 |
|
354 | |||
355 | def test_file_size(self): |
|
355 | def test_file_size(self): | |
356 | to_check = ( |
|
356 | to_check = ( | |
357 | ('c1214f7e79e02fc37156ff215cd71275450cffc3', |
|
357 | ('c1214f7e79e02fc37156ff215cd71275450cffc3', | |
358 | 'vcs/backends/BaseRepository.py', 502), |
|
358 | 'vcs/backends/BaseRepository.py', 502), | |
359 | ('d7e0d30fbcae12c90680eb095a4f5f02505ce501', |
|
359 | ('d7e0d30fbcae12c90680eb095a4f5f02505ce501', | |
360 | 'vcs/backends/hg.py', 854), |
|
360 | 'vcs/backends/hg.py', 854), | |
361 | ('6e125e7c890379446e98980d8ed60fba87d0f6d1', |
|
361 | ('6e125e7c890379446e98980d8ed60fba87d0f6d1', | |
362 | 'setup.py', 1068), |
|
362 | 'setup.py', 1068), | |
363 | ('d955cd312c17b02143c04fa1099a352b04368118', |
|
363 | ('d955cd312c17b02143c04fa1099a352b04368118', | |
364 | 'vcs/backends/base.py', 2921), |
|
364 | 'vcs/backends/base.py', 2921), | |
365 | ('ca1eb7957a54bce53b12d1a51b13452f95bc7c7e', |
|
365 | ('ca1eb7957a54bce53b12d1a51b13452f95bc7c7e', | |
366 | 'vcs/backends/base.py', 3936), |
|
366 | 'vcs/backends/base.py', 3936), | |
367 | ('f50f42baeed5af6518ef4b0cb2f1423f3851a941', |
|
367 | ('f50f42baeed5af6518ef4b0cb2f1423f3851a941', | |
368 | 'vcs/backends/base.py', 6189), |
|
368 | 'vcs/backends/base.py', 6189), | |
369 | ) |
|
369 | ) | |
370 | for revision, path, size in to_check: |
|
370 | for revision, path, size in to_check: | |
371 | self._test_file_size(revision, path, size) |
|
371 | self._test_file_size(revision, path, size) | |
372 |
|
372 | |||
373 | def _test_dir_size(self, revision, path, size): |
|
373 | def _test_dir_size(self, revision, path, size): | |
374 | node = self.repo.get_changeset(revision).get_node(path) |
|
374 | node = self.repo.get_changeset(revision).get_node(path) | |
375 | assert node.size == size |
|
375 | assert node.size == size | |
376 |
|
376 | |||
377 | def test_dir_size(self): |
|
377 | def test_dir_size(self): | |
378 | to_check = ( |
|
378 | to_check = ( | |
379 | ('5f2c6ee195929b0be80749243c18121c9864a3b3', '/', 674076), |
|
379 | ('5f2c6ee195929b0be80749243c18121c9864a3b3', '/', 674076), | |
380 | ('7ab37bc680b4aa72c34d07b230c866c28e9fc204', '/', 674049), |
|
380 | ('7ab37bc680b4aa72c34d07b230c866c28e9fc204', '/', 674049), | |
381 | ('6892503fb8f2a552cef5f4d4cc2cdbd13ae1cd2f', '/', 671830), |
|
381 | ('6892503fb8f2a552cef5f4d4cc2cdbd13ae1cd2f', '/', 671830), | |
382 | ) |
|
382 | ) | |
383 | for revision, path, size in to_check: |
|
383 | for revision, path, size in to_check: | |
384 | self._test_dir_size(revision, path, size) |
|
384 | self._test_dir_size(revision, path, size) | |
385 |
|
385 | |||
386 | def test_repo_size(self): |
|
386 | def test_repo_size(self): | |
387 | assert self.repo.size == 674076 |
|
387 | assert self.repo.size == 674076 | |
388 |
|
388 | |||
389 | def test_file_history(self): |
|
389 | def test_file_history(self): | |
390 | # we can only check if those revisions are present in the history |
|
390 | # we can only check if those revisions are present in the history | |
391 | # as we cannot update this test every time file is changed |
|
391 | # as we cannot update this test every time file is changed | |
392 | files = { |
|
392 | files = { | |
393 | 'setup.py': [ |
|
393 | 'setup.py': [ | |
394 | '54386793436c938cff89326944d4c2702340037d', |
|
394 | '54386793436c938cff89326944d4c2702340037d', | |
395 | '51d254f0ecf5df2ce50c0b115741f4cf13985dab', |
|
395 | '51d254f0ecf5df2ce50c0b115741f4cf13985dab', | |
396 | '998ed409c795fec2012b1c0ca054d99888b22090', |
|
396 | '998ed409c795fec2012b1c0ca054d99888b22090', | |
397 | '5e0eb4c47f56564395f76333f319d26c79e2fb09', |
|
397 | '5e0eb4c47f56564395f76333f319d26c79e2fb09', | |
398 | '0115510b70c7229dbc5dc49036b32e7d91d23acd', |
|
398 | '0115510b70c7229dbc5dc49036b32e7d91d23acd', | |
399 | '7cb3fd1b6d8c20ba89e2264f1c8baebc8a52d36e', |
|
399 | '7cb3fd1b6d8c20ba89e2264f1c8baebc8a52d36e', | |
400 | '2a13f185e4525f9d4b59882791a2d397b90d5ddc', |
|
400 | '2a13f185e4525f9d4b59882791a2d397b90d5ddc', | |
401 | '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e', |
|
401 | '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e', | |
402 | 'ff7ca51e58c505fec0dd2491de52c622bb7a806b', |
|
402 | 'ff7ca51e58c505fec0dd2491de52c622bb7a806b', | |
403 | ], |
|
403 | ], | |
404 | 'vcs/nodes.py': [ |
|
404 | 'vcs/nodes.py': [ | |
405 | '33fa3223355104431402a888fa77a4e9956feb3e', |
|
405 | '33fa3223355104431402a888fa77a4e9956feb3e', | |
406 | 'fa014c12c26d10ba682fadb78f2a11c24c8118e1', |
|
406 | 'fa014c12c26d10ba682fadb78f2a11c24c8118e1', | |
407 | 'e686b958768ee96af8029fe19c6050b1a8dd3b2b', |
|
407 | 'e686b958768ee96af8029fe19c6050b1a8dd3b2b', | |
408 | 'ab5721ca0a081f26bf43d9051e615af2cc99952f', |
|
408 | 'ab5721ca0a081f26bf43d9051e615af2cc99952f', | |
409 | 'c877b68d18e792a66b7f4c529ea02c8f80801542', |
|
409 | 'c877b68d18e792a66b7f4c529ea02c8f80801542', | |
410 | '4313566d2e417cb382948f8d9d7c765330356054', |
|
410 | '4313566d2e417cb382948f8d9d7c765330356054', | |
411 | '6c2303a793671e807d1cfc70134c9ca0767d98c2', |
|
411 | '6c2303a793671e807d1cfc70134c9ca0767d98c2', | |
412 | '54386793436c938cff89326944d4c2702340037d', |
|
412 | '54386793436c938cff89326944d4c2702340037d', | |
413 | '54000345d2e78b03a99d561399e8e548de3f3203', |
|
413 | '54000345d2e78b03a99d561399e8e548de3f3203', | |
414 | '1c6b3677b37ea064cb4b51714d8f7498f93f4b2b', |
|
414 | '1c6b3677b37ea064cb4b51714d8f7498f93f4b2b', | |
415 | '2d03ca750a44440fb5ea8b751176d1f36f8e8f46', |
|
415 | '2d03ca750a44440fb5ea8b751176d1f36f8e8f46', | |
416 | '2a08b128c206db48c2f0b8f70df060e6db0ae4f8', |
|
416 | '2a08b128c206db48c2f0b8f70df060e6db0ae4f8', | |
417 | '30c26513ff1eb8e5ce0e1c6b477ee5dc50e2f34b', |
|
417 | '30c26513ff1eb8e5ce0e1c6b477ee5dc50e2f34b', | |
418 | 'ac71e9503c2ca95542839af0ce7b64011b72ea7c', |
|
418 | 'ac71e9503c2ca95542839af0ce7b64011b72ea7c', | |
419 | '12669288fd13adba2a9b7dd5b870cc23ffab92d2', |
|
419 | '12669288fd13adba2a9b7dd5b870cc23ffab92d2', | |
420 | '5a0c84f3e6fe3473e4c8427199d5a6fc71a9b382', |
|
420 | '5a0c84f3e6fe3473e4c8427199d5a6fc71a9b382', | |
421 | '12f2f5e2b38e6ff3fbdb5d722efed9aa72ecb0d5', |
|
421 | '12f2f5e2b38e6ff3fbdb5d722efed9aa72ecb0d5', | |
422 | '5eab1222a7cd4bfcbabc218ca6d04276d4e27378', |
|
422 | '5eab1222a7cd4bfcbabc218ca6d04276d4e27378', | |
423 | 'f50f42baeed5af6518ef4b0cb2f1423f3851a941', |
|
423 | 'f50f42baeed5af6518ef4b0cb2f1423f3851a941', | |
424 | 'd7e390a45f6aa96f04f5e7f583ad4f867431aa25', |
|
424 | 'd7e390a45f6aa96f04f5e7f583ad4f867431aa25', | |
425 | 'f15c21f97864b4f071cddfbf2750ec2e23859414', |
|
425 | 'f15c21f97864b4f071cddfbf2750ec2e23859414', | |
426 | 'e906ef056cf539a4e4e5fc8003eaf7cf14dd8ade', |
|
426 | 'e906ef056cf539a4e4e5fc8003eaf7cf14dd8ade', | |
427 | 'ea2b108b48aa8f8c9c4a941f66c1a03315ca1c3b', |
|
427 | 'ea2b108b48aa8f8c9c4a941f66c1a03315ca1c3b', | |
428 | '84dec09632a4458f79f50ddbbd155506c460b4f9', |
|
428 | '84dec09632a4458f79f50ddbbd155506c460b4f9', | |
429 | '0115510b70c7229dbc5dc49036b32e7d91d23acd', |
|
429 | '0115510b70c7229dbc5dc49036b32e7d91d23acd', | |
430 | '2a13f185e4525f9d4b59882791a2d397b90d5ddc', |
|
430 | '2a13f185e4525f9d4b59882791a2d397b90d5ddc', | |
431 | '3bf1c5868e570e39569d094f922d33ced2fa3b2b', |
|
431 | '3bf1c5868e570e39569d094f922d33ced2fa3b2b', | |
432 | 'b8d04012574729d2c29886e53b1a43ef16dd00a1', |
|
432 | 'b8d04012574729d2c29886e53b1a43ef16dd00a1', | |
433 | '6970b057cffe4aab0a792aa634c89f4bebf01441', |
|
433 | '6970b057cffe4aab0a792aa634c89f4bebf01441', | |
434 | 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f', |
|
434 | 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f', | |
435 | 'ff7ca51e58c505fec0dd2491de52c622bb7a806b', |
|
435 | 'ff7ca51e58c505fec0dd2491de52c622bb7a806b', | |
436 | ], |
|
436 | ], | |
437 | 'vcs/backends/git.py': [ |
|
437 | 'vcs/backends/git.py': [ | |
438 | '4cf116ad5a457530381135e2f4c453e68a1b0105', |
|
438 | '4cf116ad5a457530381135e2f4c453e68a1b0105', | |
439 | '9a751d84d8e9408e736329767387f41b36935153', |
|
439 | '9a751d84d8e9408e736329767387f41b36935153', | |
440 | 'cb681fb539c3faaedbcdf5ca71ca413425c18f01', |
|
440 | 'cb681fb539c3faaedbcdf5ca71ca413425c18f01', | |
441 | '428f81bb652bcba8d631bce926e8834ff49bdcc6', |
|
441 | '428f81bb652bcba8d631bce926e8834ff49bdcc6', | |
442 | '180ab15aebf26f98f714d8c68715e0f05fa6e1c7', |
|
442 | '180ab15aebf26f98f714d8c68715e0f05fa6e1c7', | |
443 | '2b8e07312a2e89e92b90426ab97f349f4bce2a3a', |
|
443 | '2b8e07312a2e89e92b90426ab97f349f4bce2a3a', | |
444 | '50e08c506174d8645a4bb517dd122ac946a0f3bf', |
|
444 | '50e08c506174d8645a4bb517dd122ac946a0f3bf', | |
445 | '54000345d2e78b03a99d561399e8e548de3f3203', |
|
445 | '54000345d2e78b03a99d561399e8e548de3f3203', | |
446 | ], |
|
446 | ], | |
447 | } |
|
447 | } | |
448 | for path, revs in files.items(): |
|
448 | for path, revs in files.items(): | |
449 | node = self.repo.get_changeset(revs[0]).get_node(path) |
|
449 | node = self.repo.get_changeset(revs[0]).get_node(path) | |
450 | node_revs = [chset.raw_id for chset in node.history] |
|
450 | node_revs = [chset.raw_id for chset in node.history] | |
451 | assert set(revs).issubset(set(node_revs)), "We assumed that %s is subset of revisions for which file %s " \ |
|
451 | assert set(revs).issubset(set(node_revs)), "We assumed that %s is subset of revisions for which file %s " \ | |
452 | "has been changed, and history of that node returned: %s" \ |
|
452 | "has been changed, and history of that node returned: %s" \ | |
453 | % (revs, path, node_revs) |
|
453 | % (revs, path, node_revs) | |
454 |
|
454 | |||
455 | def test_file_annotate(self): |
|
455 | def test_file_annotate(self): | |
456 | files = { |
|
456 | files = { | |
457 | 'vcs/backends/__init__.py': { |
|
457 | 'vcs/backends/__init__.py': { | |
458 | 'c1214f7e79e02fc37156ff215cd71275450cffc3': { |
|
458 | 'c1214f7e79e02fc37156ff215cd71275450cffc3': { | |
459 | 'lines_no': 1, |
|
459 | 'lines_no': 1, | |
460 | 'changesets': [ |
|
460 | 'changesets': [ | |
461 | 'c1214f7e79e02fc37156ff215cd71275450cffc3', |
|
461 | 'c1214f7e79e02fc37156ff215cd71275450cffc3', | |
462 | ], |
|
462 | ], | |
463 | }, |
|
463 | }, | |
464 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647': { |
|
464 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647': { | |
465 | 'lines_no': 21, |
|
465 | 'lines_no': 21, | |
466 | 'changesets': [ |
|
466 | 'changesets': [ | |
467 | '49d3fd156b6f7db46313fac355dca1a0b94a0017', |
|
467 | '49d3fd156b6f7db46313fac355dca1a0b94a0017', | |
468 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
468 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
469 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
469 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
470 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
470 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
471 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
471 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
472 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
472 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
473 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
473 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
474 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
474 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
475 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
475 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
476 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
476 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
477 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
477 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
478 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
478 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
479 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
479 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
480 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
480 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
481 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
481 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
482 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
482 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
483 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
483 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
484 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
484 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
485 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
485 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
486 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
486 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
487 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
487 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
488 | ], |
|
488 | ], | |
489 | }, |
|
489 | }, | |
490 | 'e29b67bd158580fc90fc5e9111240b90e6e86064': { |
|
490 | 'e29b67bd158580fc90fc5e9111240b90e6e86064': { | |
491 | 'lines_no': 32, |
|
491 | 'lines_no': 32, | |
492 | 'changesets': [ |
|
492 | 'changesets': [ | |
493 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
493 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
494 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
494 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
495 | '5eab1222a7cd4bfcbabc218ca6d04276d4e27378', |
|
495 | '5eab1222a7cd4bfcbabc218ca6d04276d4e27378', | |
496 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
496 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
497 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
497 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
498 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', |
|
498 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
499 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
499 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
500 | '54000345d2e78b03a99d561399e8e548de3f3203', |
|
500 | '54000345d2e78b03a99d561399e8e548de3f3203', | |
501 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
501 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
502 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
502 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
503 | '78c3f0c23b7ee935ec276acb8b8212444c33c396', |
|
503 | '78c3f0c23b7ee935ec276acb8b8212444c33c396', | |
504 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', |
|
504 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
505 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', |
|
505 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
506 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', |
|
506 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
507 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', |
|
507 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
508 | '2a13f185e4525f9d4b59882791a2d397b90d5ddc', |
|
508 | '2a13f185e4525f9d4b59882791a2d397b90d5ddc', | |
509 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', |
|
509 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
510 | '78c3f0c23b7ee935ec276acb8b8212444c33c396', |
|
510 | '78c3f0c23b7ee935ec276acb8b8212444c33c396', | |
511 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', |
|
511 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
512 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', |
|
512 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
513 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', |
|
513 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
514 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
514 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
515 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
515 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
516 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
516 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
517 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
517 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
518 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', |
|
518 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
519 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
519 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
520 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', |
|
520 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
521 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', |
|
521 | '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
522 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
522 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
523 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
523 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
524 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', |
|
524 | '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
525 | ], |
|
525 | ], | |
526 | }, |
|
526 | }, | |
527 | }, |
|
527 | }, | |
528 | } |
|
528 | } | |
529 |
|
529 | |||
530 | for fname, revision_dict in files.items(): |
|
530 | for fname, revision_dict in files.items(): | |
531 | for rev, data in revision_dict.items(): |
|
531 | for rev, data in revision_dict.items(): | |
532 | cs = self.repo.get_changeset(rev) |
|
532 | cs = self.repo.get_changeset(rev) | |
533 |
|
533 | |||
534 | l1_1 = [x[1] for x in cs.get_file_annotate(fname)] |
|
534 | l1_1 = [x[1] for x in cs.get_file_annotate(fname)] | |
535 | l1_2 = [x[2]().raw_id for x in cs.get_file_annotate(fname)] |
|
535 | l1_2 = [x[2]().raw_id for x in cs.get_file_annotate(fname)] | |
536 | assert l1_1 == l1_2 |
|
536 | assert l1_1 == l1_2 | |
537 | l1 = l1_1 |
|
537 | l1 = l1_1 | |
538 | l2 = files[fname][rev]['changesets'] |
|
538 | l2 = files[fname][rev]['changesets'] | |
539 | assert l1 == l2, "The lists of revision for %s@rev %s" \ |
|
539 | assert l1 == l2, "The lists of revision for %s@rev %s" \ | |
540 | "from annotation list should match each other, " \ |
|
540 | "from annotation list should match each other, " \ | |
541 | "got \n%s \nvs \n%s " % (fname, rev, l1, l2) |
|
541 | "got \n%s \nvs \n%s " % (fname, rev, l1, l2) | |
542 |
|
542 | |||
543 | def test_files_state(self): |
|
543 | def test_files_state(self): | |
544 | """ |
|
544 | """ | |
545 | Tests state of FileNodes. |
|
545 | Tests state of FileNodes. | |
546 | """ |
|
546 | """ | |
547 | node = self.repo \ |
|
547 | node = self.repo \ | |
548 | .get_changeset('e6ea6d16e2f26250124a1f4b4fe37a912f9d86a0') \ |
|
548 | .get_changeset('e6ea6d16e2f26250124a1f4b4fe37a912f9d86a0') \ | |
549 | .get_node('vcs/utils/diffs.py') |
|
549 | .get_node('vcs/utils/diffs.py') | |
550 | assert node.state, NodeState.ADDED |
|
550 | assert node.state, NodeState.ADDED | |
551 | assert node.added |
|
551 | assert node.added | |
552 | assert not node.changed |
|
552 | assert not node.changed | |
553 | assert not node.not_changed |
|
553 | assert not node.not_changed | |
554 | assert not node.removed |
|
554 | assert not node.removed | |
555 |
|
555 | |||
556 | node = self.repo \ |
|
556 | node = self.repo \ | |
557 | .get_changeset('33fa3223355104431402a888fa77a4e9956feb3e') \ |
|
557 | .get_changeset('33fa3223355104431402a888fa77a4e9956feb3e') \ | |
558 | .get_node('.hgignore') |
|
558 | .get_node('.hgignore') | |
559 | assert node.state, NodeState.CHANGED |
|
559 | assert node.state, NodeState.CHANGED | |
560 | assert not node.added |
|
560 | assert not node.added | |
561 | assert node.changed |
|
561 | assert node.changed | |
562 | assert not node.not_changed |
|
562 | assert not node.not_changed | |
563 | assert not node.removed |
|
563 | assert not node.removed | |
564 |
|
564 | |||
565 | node = self.repo \ |
|
565 | node = self.repo \ | |
566 | .get_changeset('e29b67bd158580fc90fc5e9111240b90e6e86064') \ |
|
566 | .get_changeset('e29b67bd158580fc90fc5e9111240b90e6e86064') \ | |
567 | .get_node('setup.py') |
|
567 | .get_node('setup.py') | |
568 | assert node.state, NodeState.NOT_CHANGED |
|
568 | assert node.state, NodeState.NOT_CHANGED | |
569 | assert not node.added |
|
569 | assert not node.added | |
570 | assert not node.changed |
|
570 | assert not node.changed | |
571 | assert node.not_changed |
|
571 | assert node.not_changed | |
572 | assert not node.removed |
|
572 | assert not node.removed | |
573 |
|
573 | |||
574 | # If node has REMOVED state then trying to fetch it would raise |
|
574 | # If node has REMOVED state then trying to fetch it would raise | |
575 | # ChangesetError exception |
|
575 | # ChangesetError exception | |
576 | chset = self.repo.get_changeset( |
|
576 | chset = self.repo.get_changeset( | |
577 | 'fa6600f6848800641328adbf7811fd2372c02ab2') |
|
577 | 'fa6600f6848800641328adbf7811fd2372c02ab2') | |
578 | path = 'vcs/backends/BaseRepository.py' |
|
578 | path = 'vcs/backends/BaseRepository.py' | |
579 | with pytest.raises(NodeDoesNotExistError): |
|
579 | with pytest.raises(NodeDoesNotExistError): | |
580 | chset.get_node(path) |
|
580 | chset.get_node(path) | |
581 | # but it would be one of ``removed`` (changeset's attribute) |
|
581 | # but it would be one of ``removed`` (changeset's attribute) | |
582 | assert path in [rf.path for rf in chset.removed] |
|
582 | assert path in [rf.path for rf in chset.removed] | |
583 |
|
583 | |||
584 | chset = self.repo.get_changeset( |
|
584 | chset = self.repo.get_changeset( | |
585 | '54386793436c938cff89326944d4c2702340037d') |
|
585 | '54386793436c938cff89326944d4c2702340037d') | |
586 | changed = ['setup.py', 'tests/test_nodes.py', 'vcs/backends/hg.py', |
|
586 | changed = ['setup.py', 'tests/test_nodes.py', 'vcs/backends/hg.py', | |
587 | 'vcs/nodes.py'] |
|
587 | 'vcs/nodes.py'] | |
588 | assert set(changed) == set([f.path for f in chset.changed]) |
|
588 | assert set(changed) == set([f.path for f in chset.changed]) | |
589 |
|
589 | |||
590 | def test_commit_message_is_str(self): |
|
590 | def test_commit_message_is_str(self): | |
591 | for cs in self.repo: |
|
591 | for cs in self.repo: | |
592 | assert isinstance(cs.message, str) |
|
592 | assert isinstance(cs.message, str) | |
593 |
|
593 | |||
594 | def test_changeset_author_is_str(self): |
|
594 | def test_changeset_author_is_str(self): | |
595 | for cs in self.repo: |
|
595 | for cs in self.repo: | |
596 | assert isinstance(cs.author, str) |
|
596 | assert isinstance(cs.author, str) | |
597 |
|
597 | |||
598 | def test_repo_files_content_is_bytes(self): |
|
598 | def test_repo_files_content_is_bytes(self): | |
599 | changeset = self.repo.get_changeset() |
|
599 | changeset = self.repo.get_changeset() | |
600 | for node in changeset.get_node('/'): |
|
600 | for node in changeset.get_node('/'): | |
601 | if node.is_file(): |
|
601 | if node.is_file(): | |
602 | assert isinstance(node.content, bytes) |
|
602 | assert isinstance(node.content, bytes) | |
603 |
|
603 | |||
604 | def test_wrong_path(self): |
|
604 | def test_wrong_path(self): | |
605 | # There is 'setup.py' in the root dir but not there: |
|
605 | # There is 'setup.py' in the root dir but not there: | |
606 | path = 'foo/bar/setup.py' |
|
606 | path = 'foo/bar/setup.py' | |
607 | tip = self.repo.get_changeset() |
|
607 | tip = self.repo.get_changeset() | |
608 | with pytest.raises(VCSError): |
|
608 | with pytest.raises(VCSError): | |
609 | tip.get_node(path) |
|
609 | tip.get_node(path) | |
610 |
|
610 | |||
611 | def test_author_email(self): |
|
611 | def test_author_email(self): | |
612 | assert 'marcin@python-blog.com' == self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3').author_email |
|
612 | assert 'marcin@python-blog.com' == self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3').author_email | |
613 | assert 'lukasz.balcerzak@python-center.pl' == self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b').author_email |
|
613 | assert 'lukasz.balcerzak@python-center.pl' == self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b').author_email | |
614 | assert '' == self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992').author_email |
|
614 | assert '' == self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992').author_email | |
615 |
|
615 | |||
616 | def test_author_username(self): |
|
616 | def test_author_username(self): | |
617 | assert 'Marcin Kuzminski' == self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3').author_name |
|
617 | assert 'Marcin Kuzminski' == self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3').author_name | |
618 | assert 'Lukasz Balcerzak' == self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b').author_name |
|
618 | assert 'Lukasz Balcerzak' == self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b').author_name | |
619 | assert 'marcink none@none' == self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992').author_name |
|
619 | assert 'marcink none@none' == self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992').author_name | |
620 |
|
620 | |||
621 |
|
621 | |||
622 | class TestGitSpecificWithRepo(_BackendTestMixin): |
|
622 | class TestGitSpecificWithRepo(_BackendTestMixin): | |
623 | backend_alias = 'git' |
|
623 | backend_alias = 'git' | |
624 |
|
624 | |||
625 | @classmethod |
|
625 | @classmethod | |
626 | def _get_commits(cls): |
|
626 | def _get_commits(cls): | |
627 | return [ |
|
627 | return [ | |
628 | { |
|
628 | { | |
629 | 'message': 'Initial', |
|
629 | 'message': 'Initial', | |
630 | 'author': 'Joe Doe <joe.doe@example.com>', |
|
630 | 'author': 'Joe Doe <joe.doe@example.com>', | |
631 | 'date': datetime.datetime(2010, 1, 1, 20), |
|
631 | 'date': datetime.datetime(2010, 1, 1, 20), | |
632 | 'added': [ |
|
632 | 'added': [ | |
633 | FileNode('foobar/static/js/admin/base.js', content='base'), |
|
633 | FileNode('foobar/static/js/admin/base.js', content='base'), | |
634 | FileNode('foobar/static/admin', content='admin', |
|
634 | FileNode('foobar/static/admin', content='admin', | |
635 | mode=0o120000), # this is a link |
|
635 | mode=0o120000), # this is a link | |
636 | FileNode('foo', content='foo'), |
|
636 | FileNode('foo', content='foo'), | |
637 | ], |
|
637 | ], | |
638 | }, |
|
638 | }, | |
639 | { |
|
639 | { | |
640 | 'message': 'Second', |
|
640 | 'message': 'Second', | |
641 | 'author': 'Joe Doe <joe.doe@example.com>', |
|
641 | 'author': 'Joe Doe <joe.doe@example.com>', | |
642 | 'date': datetime.datetime(2010, 1, 1, 22), |
|
642 | 'date': datetime.datetime(2010, 1, 1, 22), | |
643 | 'added': [ |
|
643 | 'added': [ | |
644 | FileNode('foo2', content='foo2'), |
|
644 | FileNode('foo2', content='foo2'), | |
645 | ], |
|
645 | ], | |
646 | }, |
|
646 | }, | |
647 | ] |
|
647 | ] | |
648 |
|
648 | |||
649 | def test_paths_slow_traversing(self): |
|
649 | def test_paths_slow_traversing(self): | |
650 | cs = self.repo.get_changeset() |
|
650 | cs = self.repo.get_changeset() | |
651 | assert cs.get_node('foobar').get_node('static').get_node('js').get_node('admin').get_node('base.js').content == b'base' |
|
651 | assert cs.get_node('foobar').get_node('static').get_node('js').get_node('admin').get_node('base.js').content == b'base' | |
652 |
|
652 | |||
653 | def test_paths_fast_traversing(self): |
|
653 | def test_paths_fast_traversing(self): | |
654 | cs = self.repo.get_changeset() |
|
654 | cs = self.repo.get_changeset() | |
655 | assert cs.get_node('foobar/static/js/admin/base.js').content == b'base' |
|
655 | assert cs.get_node('foobar/static/js/admin/base.js').content == b'base' | |
656 |
|
656 | |||
657 | def test_workdir_get_branch(self): |
|
657 | def test_workdir_get_branch(self): | |
658 | self.repo.run_git_command(['checkout', '-b', 'production']) |
|
658 | self.repo.run_git_command(['checkout', '-b', 'production']) | |
659 | # Regression test: one of following would fail if we don't check |
|
659 | # Regression test: one of following would fail if we don't check | |
660 | # .git/HEAD file |
|
660 | # .git/HEAD file | |
661 | self.repo.run_git_command(['checkout', 'production']) |
|
661 | self.repo.run_git_command(['checkout', 'production']) | |
662 | assert self.repo.workdir.get_branch() == 'production' |
|
662 | assert self.repo.workdir.get_branch() == 'production' | |
663 | self.repo.run_git_command(['checkout', 'master']) |
|
663 | self.repo.run_git_command(['checkout', 'master']) | |
664 | assert self.repo.workdir.get_branch() == 'master' |
|
664 | assert self.repo.workdir.get_branch() == 'master' | |
665 |
|
665 | |||
666 | def test_get_diff_runs_git_command_with_hashes(self): |
|
666 | def test_get_diff_runs_git_command_with_hashes(self): | |
667 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) |
|
667 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) | |
668 | self.repo.get_diff(0, 1) |
|
668 | self.repo.get_diff(0, 1) | |
669 | self.repo._run_git_command.assert_called_once_with( |
|
669 | self.repo._run_git_command.assert_called_once_with( | |
670 | ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40', |
|
670 | ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40', | |
671 | self.repo._get_revision(0), self.repo._get_revision(1)], cwd=self.repo.path) |
|
671 | self.repo._get_revision(0), self.repo._get_revision(1)], cwd=self.repo.path) | |
672 |
|
672 | |||
673 | def test_get_diff_runs_git_command_with_str_hashes(self): |
|
673 | def test_get_diff_runs_git_command_with_str_hashes(self): | |
674 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) |
|
674 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) | |
675 | self.repo.get_diff(self.repo.EMPTY_CHANGESET, 1) |
|
675 | self.repo.get_diff(self.repo.EMPTY_CHANGESET, 1) | |
676 | self.repo._run_git_command.assert_called_once_with( |
|
676 | self.repo._run_git_command.assert_called_once_with( | |
677 | ['show', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40', |
|
677 | ['show', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40', | |
678 | self.repo._get_revision(1)], cwd=self.repo.path) |
|
678 | self.repo._get_revision(1)], cwd=self.repo.path) | |
679 |
|
679 | |||
680 | def test_get_diff_runs_git_command_with_path_if_its_given(self): |
|
680 | def test_get_diff_runs_git_command_with_path_if_its_given(self): | |
681 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) |
|
681 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) | |
682 | self.repo.get_diff(0, 1, 'foo') |
|
682 | self.repo.get_diff(0, 1, 'foo') | |
683 | self.repo._run_git_command.assert_called_once_with( |
|
683 | self.repo._run_git_command.assert_called_once_with( | |
684 | ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40', |
|
684 | ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40', | |
685 | self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) |
|
685 | self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) | |
686 |
|
686 | |||
687 | def test_get_diff_does_not_sanitize_valid_context(self): |
|
687 | def test_get_diff_does_not_sanitize_valid_context(self): | |
688 | almost_overflowed_long_int = 2**31-1 |
|
688 | almost_overflowed_long_int = 2**31-1 | |
689 |
|
689 | |||
690 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) |
|
690 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) | |
691 | self.repo.get_diff(0, 1, 'foo', context=almost_overflowed_long_int) |
|
691 | self.repo.get_diff(0, 1, 'foo', context=almost_overflowed_long_int) | |
692 | self.repo._run_git_command.assert_called_once_with( |
|
692 | self.repo._run_git_command.assert_called_once_with( | |
693 | ['diff', '-U' + str(almost_overflowed_long_int), '--full-index', '--binary', '-p', '-M', '--abbrev=40', |
|
693 | ['diff', '-U' + str(almost_overflowed_long_int), '--full-index', '--binary', '-p', '-M', '--abbrev=40', | |
694 | self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) |
|
694 | self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) | |
695 |
|
695 | |||
696 | def test_get_diff_sanitizes_overflowing_context(self): |
|
696 | def test_get_diff_sanitizes_overflowing_context(self): | |
697 | overflowed_long_int = 2**31 |
|
697 | overflowed_long_int = 2**31 | |
698 | sanitized_overflowed_long_int = overflowed_long_int-1 |
|
698 | sanitized_overflowed_long_int = overflowed_long_int-1 | |
699 |
|
699 | |||
700 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) |
|
700 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) | |
701 | self.repo.get_diff(0, 1, 'foo', context=overflowed_long_int) |
|
701 | self.repo.get_diff(0, 1, 'foo', context=overflowed_long_int) | |
702 |
|
702 | |||
703 | self.repo._run_git_command.assert_called_once_with( |
|
703 | self.repo._run_git_command.assert_called_once_with( | |
704 | ['diff', '-U' + str(sanitized_overflowed_long_int), '--full-index', '--binary', '-p', '-M', '--abbrev=40', |
|
704 | ['diff', '-U' + str(sanitized_overflowed_long_int), '--full-index', '--binary', '-p', '-M', '--abbrev=40', | |
705 | self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) |
|
705 | self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) | |
706 |
|
706 | |||
707 | def test_get_diff_does_not_sanitize_zero_context(self): |
|
707 | def test_get_diff_does_not_sanitize_zero_context(self): | |
708 | zero_context = 0 |
|
708 | zero_context = 0 | |
709 |
|
709 | |||
710 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) |
|
710 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) | |
711 | self.repo.get_diff(0, 1, 'foo', context=zero_context) |
|
711 | self.repo.get_diff(0, 1, 'foo', context=zero_context) | |
712 |
|
712 | |||
713 | self.repo._run_git_command.assert_called_once_with( |
|
713 | self.repo._run_git_command.assert_called_once_with( | |
714 | ['diff', '-U' + str(zero_context), '--full-index', '--binary', '-p', '-M', '--abbrev=40', |
|
714 | ['diff', '-U' + str(zero_context), '--full-index', '--binary', '-p', '-M', '--abbrev=40', | |
715 | self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) |
|
715 | self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) | |
716 |
|
716 | |||
717 | def test_get_diff_sanitizes_negative_context(self): |
|
717 | def test_get_diff_sanitizes_negative_context(self): | |
718 | negative_context = -10 |
|
718 | negative_context = -10 | |
719 |
|
719 | |||
720 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) |
|
720 | self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) | |
721 | self.repo.get_diff(0, 1, 'foo', context=negative_context) |
|
721 | self.repo.get_diff(0, 1, 'foo', context=negative_context) | |
722 |
|
722 | |||
723 | self.repo._run_git_command.assert_called_once_with( |
|
723 | self.repo._run_git_command.assert_called_once_with( | |
724 | ['diff', '-U0', '--full-index', '--binary', '-p', '-M', '--abbrev=40', |
|
724 | ['diff', '-U0', '--full-index', '--binary', '-p', '-M', '--abbrev=40', | |
725 | self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) |
|
725 | self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) | |
726 |
|
726 | |||
727 |
|
727 | |||
728 | class TestGitRegression(_BackendTestMixin): |
|
728 | class TestGitRegression(_BackendTestMixin): | |
729 | backend_alias = 'git' |
|
729 | backend_alias = 'git' | |
730 |
|
730 | |||
731 | @classmethod |
|
731 | @classmethod | |
732 | def _get_commits(cls): |
|
732 | def _get_commits(cls): | |
733 | return [ |
|
733 | return [ | |
734 | { |
|
734 | { | |
735 | 'message': 'Initial', |
|
735 | 'message': 'Initial', | |
736 | 'author': 'Joe Doe <joe.doe@example.com>', |
|
736 | 'author': 'Joe Doe <joe.doe@example.com>', | |
737 | 'date': datetime.datetime(2010, 1, 1, 20), |
|
737 | 'date': datetime.datetime(2010, 1, 1, 20), | |
738 | 'added': [ |
|
738 | 'added': [ | |
739 | FileNode('bot/__init__.py', content='base'), |
|
739 | FileNode('bot/__init__.py', content='base'), | |
740 | FileNode('bot/templates/404.html', content='base'), |
|
740 | FileNode('bot/templates/404.html', content='base'), | |
741 | FileNode('bot/templates/500.html', content='base'), |
|
741 | FileNode('bot/templates/500.html', content='base'), | |
742 | ], |
|
742 | ], | |
743 | }, |
|
743 | }, | |
744 | { |
|
744 | { | |
745 | 'message': 'Second', |
|
745 | 'message': 'Second', | |
746 | 'author': 'Joe Doe <joe.doe@example.com>', |
|
746 | 'author': 'Joe Doe <joe.doe@example.com>', | |
747 | 'date': datetime.datetime(2010, 1, 1, 22), |
|
747 | 'date': datetime.datetime(2010, 1, 1, 22), | |
748 | 'added': [ |
|
748 | 'added': [ | |
749 | FileNode('bot/build/migrations/1.py', content='foo2'), |
|
749 | FileNode('bot/build/migrations/1.py', content='foo2'), | |
750 | FileNode('bot/build/migrations/2.py', content='foo2'), |
|
750 | FileNode('bot/build/migrations/2.py', content='foo2'), | |
751 | FileNode('bot/build/static/templates/f.html', content='foo2'), |
|
751 | FileNode('bot/build/static/templates/f.html', content='foo2'), | |
752 | FileNode('bot/build/static/templates/f1.html', content='foo2'), |
|
752 | FileNode('bot/build/static/templates/f1.html', content='foo2'), | |
753 | FileNode('bot/build/templates/err.html', content='foo2'), |
|
753 | FileNode('bot/build/templates/err.html', content='foo2'), | |
754 | FileNode('bot/build/templates/err2.html', content='foo2'), |
|
754 | FileNode('bot/build/templates/err2.html', content='foo2'), | |
755 | ], |
|
755 | ], | |
756 | }, |
|
756 | }, | |
757 | ] |
|
757 | ] | |
758 |
|
758 | |||
759 | def test_similar_paths(self): |
|
759 | def test_similar_paths(self): | |
760 | cs = self.repo.get_changeset() |
|
760 | cs = self.repo.get_changeset() | |
761 | paths = lambda *n: [x.path for x in n] |
|
761 | def paths(*n): | |
|
762 | return [x.path for x in n] | |||
762 | assert paths(*cs.get_nodes('bot')) == ['bot/build', 'bot/templates', 'bot/__init__.py'] |
|
763 | assert paths(*cs.get_nodes('bot')) == ['bot/build', 'bot/templates', 'bot/__init__.py'] | |
763 | assert paths(*cs.get_nodes('bot/build')) == ['bot/build/migrations', 'bot/build/static', 'bot/build/templates'] |
|
764 | assert paths(*cs.get_nodes('bot/build')) == ['bot/build/migrations', 'bot/build/static', 'bot/build/templates'] | |
764 | assert paths(*cs.get_nodes('bot/build/static')) == ['bot/build/static/templates'] |
|
765 | assert paths(*cs.get_nodes('bot/build/static')) == ['bot/build/static/templates'] | |
765 | # this get_nodes below causes troubles ! |
|
766 | # this get_nodes below causes troubles ! | |
766 | assert paths(*cs.get_nodes('bot/build/static/templates')) == ['bot/build/static/templates/f.html', 'bot/build/static/templates/f1.html'] |
|
767 | assert paths(*cs.get_nodes('bot/build/static/templates')) == ['bot/build/static/templates/f.html', 'bot/build/static/templates/f1.html'] | |
767 | assert paths(*cs.get_nodes('bot/build/templates')) == ['bot/build/templates/err.html', 'bot/build/templates/err2.html'] |
|
768 | assert paths(*cs.get_nodes('bot/build/templates')) == ['bot/build/templates/err.html', 'bot/build/templates/err2.html'] | |
768 | assert paths(*cs.get_nodes('bot/templates/')) == ['bot/templates/404.html', 'bot/templates/500.html'] |
|
769 | assert paths(*cs.get_nodes('bot/templates/')) == ['bot/templates/404.html', 'bot/templates/500.html'] | |
769 |
|
770 | |||
770 |
|
771 | |||
771 | class TestGitHooks(object): |
|
772 | class TestGitHooks(object): | |
772 | """ |
|
773 | """ | |
773 | Tests related to hook functionality of Git repositories. |
|
774 | Tests related to hook functionality of Git repositories. | |
774 | """ |
|
775 | """ | |
775 |
|
776 | |||
776 | def setup_method(self): |
|
777 | def setup_method(self): | |
777 | # For each run we want a fresh repo. |
|
778 | # For each run we want a fresh repo. | |
778 | self.repo_directory = get_new_dir("githookrepo") |
|
779 | self.repo_directory = get_new_dir("githookrepo") | |
779 | self.repo = GitRepository(self.repo_directory, create=True) |
|
780 | self.repo = GitRepository(self.repo_directory, create=True) | |
780 |
|
781 | |||
781 | # Create a dictionary where keys are hook names, and values are paths to |
|
782 | # Create a dictionary where keys are hook names, and values are paths to | |
782 | # them in the non-bare repo. Deduplicates code in tests a bit. |
|
783 | # them in the non-bare repo. Deduplicates code in tests a bit. | |
783 | self.pre_receive = os.path.join(self.repo.path, '.git', 'hooks', "pre-receive") |
|
784 | self.pre_receive = os.path.join(self.repo.path, '.git', 'hooks', "pre-receive") | |
784 | self.post_receive = os.path.join(self.repo.path, '.git', 'hooks', "post-receive") |
|
785 | self.post_receive = os.path.join(self.repo.path, '.git', 'hooks', "post-receive") | |
785 | self.kallithea_hooks = { |
|
786 | self.kallithea_hooks = { | |
786 | "pre-receive": self.pre_receive, |
|
787 | "pre-receive": self.pre_receive, | |
787 | "post-receive": self.post_receive, |
|
788 | "post-receive": self.post_receive, | |
788 | } |
|
789 | } | |
789 |
|
790 | |||
790 | def test_hooks_created_if_missing(self): |
|
791 | def test_hooks_created_if_missing(self): | |
791 | """ |
|
792 | """ | |
792 | Tests if hooks are installed in repository if they are missing. |
|
793 | Tests if hooks are installed in repository if they are missing. | |
793 | """ |
|
794 | """ | |
794 |
|
795 | |||
795 | for hook, hook_path in self.kallithea_hooks.items(): |
|
796 | for hook, hook_path in self.kallithea_hooks.items(): | |
796 | if os.path.exists(hook_path): |
|
797 | if os.path.exists(hook_path): | |
797 | os.remove(hook_path) |
|
798 | os.remove(hook_path) | |
798 |
|
799 | |||
799 | ScmModel().install_git_hooks(self.repo) |
|
800 | ScmModel().install_git_hooks(self.repo) | |
800 |
|
801 | |||
801 | assert not os.path.exists(self.pre_receive) |
|
802 | assert not os.path.exists(self.pre_receive) | |
802 | assert os.path.exists(self.post_receive) |
|
803 | assert os.path.exists(self.post_receive) | |
803 |
|
804 | |||
804 | def test_kallithea_hooks_updated(self): |
|
805 | def test_kallithea_hooks_updated(self): | |
805 | """ |
|
806 | """ | |
806 | Tests if hooks are updated if they are Kallithea hooks already. |
|
807 | Tests if hooks are updated if they are Kallithea hooks already. | |
807 | """ |
|
808 | """ | |
808 |
|
809 | |||
809 | for hook, hook_path in self.kallithea_hooks.items(): |
|
810 | for hook, hook_path in self.kallithea_hooks.items(): | |
810 | with open(hook_path, "w") as f: |
|
811 | with open(hook_path, "w") as f: | |
811 | f.write("KALLITHEA_HOOK_VER=0.0.0\nJUST_BOGUS") |
|
812 | f.write("KALLITHEA_HOOK_VER=0.0.0\nJUST_BOGUS") | |
812 |
|
813 | |||
813 | ScmModel().install_git_hooks(self.repo) |
|
814 | ScmModel().install_git_hooks(self.repo) | |
814 |
|
815 | |||
815 | assert not os.path.exists(self.pre_receive) |
|
816 | assert not os.path.exists(self.pre_receive) | |
816 | with open(self.post_receive) as f: |
|
817 | with open(self.post_receive) as f: | |
817 | assert "JUST_BOGUS" not in f.read() |
|
818 | assert "JUST_BOGUS" not in f.read() | |
818 |
|
819 | |||
819 | def test_custom_hooks_untouched(self): |
|
820 | def test_custom_hooks_untouched(self): | |
820 | """ |
|
821 | """ | |
821 | Tests if hooks are left untouched if they are not Kallithea hooks. |
|
822 | Tests if hooks are left untouched if they are not Kallithea hooks. | |
822 | """ |
|
823 | """ | |
823 |
|
824 | |||
824 | for hook, hook_path in self.kallithea_hooks.items(): |
|
825 | for hook, hook_path in self.kallithea_hooks.items(): | |
825 | with open(hook_path, "w") as f: |
|
826 | with open(hook_path, "w") as f: | |
826 | f.write("#!/bin/bash\n#CUSTOM_HOOK") |
|
827 | f.write("#!/bin/bash\n#CUSTOM_HOOK") | |
827 |
|
828 | |||
828 | ScmModel().install_git_hooks(self.repo) |
|
829 | ScmModel().install_git_hooks(self.repo) | |
829 |
|
830 | |||
830 | for hook, hook_path in self.kallithea_hooks.items(): |
|
831 | for hook, hook_path in self.kallithea_hooks.items(): | |
831 | with open(hook_path) as f: |
|
832 | with open(hook_path) as f: | |
832 | assert "CUSTOM_HOOK" in f.read() |
|
833 | assert "CUSTOM_HOOK" in f.read() | |
833 |
|
834 | |||
834 | def test_custom_hooks_forced_update(self): |
|
835 | def test_custom_hooks_forced_update(self): | |
835 | """ |
|
836 | """ | |
836 | Tests if hooks are forcefully updated even though they are custom hooks. |
|
837 | Tests if hooks are forcefully updated even though they are custom hooks. | |
837 | """ |
|
838 | """ | |
838 |
|
839 | |||
839 | for hook, hook_path in self.kallithea_hooks.items(): |
|
840 | for hook, hook_path in self.kallithea_hooks.items(): | |
840 | with open(hook_path, "w") as f: |
|
841 | with open(hook_path, "w") as f: | |
841 | f.write("#!/bin/bash\n#CUSTOM_HOOK") |
|
842 | f.write("#!/bin/bash\n#CUSTOM_HOOK") | |
842 |
|
843 | |||
843 | ScmModel().install_git_hooks(self.repo, force=True) |
|
844 | ScmModel().install_git_hooks(self.repo, force=True) | |
844 |
|
845 | |||
845 | with open(self.pre_receive) as f: |
|
846 | with open(self.pre_receive) as f: | |
846 | assert "KALLITHEA_HOOK_VER" not in f.read() |
|
847 | assert "KALLITHEA_HOOK_VER" not in f.read() | |
847 | with open(self.post_receive) as f: |
|
848 | with open(self.post_receive) as f: | |
848 | assert "KALLITHEA_HOOK_VER" in f.read() |
|
849 | assert "KALLITHEA_HOOK_VER" in f.read() |
General Comments 0
You need to be logged in to leave comments.
Login now