##// END OF EJS Templates
tests: change lib tests to use proper pyramid mocks.
marcink -
r2318:03c88275 default
parent child Browse files
Show More
@@ -1,624 +1,623 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 """
22 """
23 Package for testing various lib/helper functions in rhodecode
23 Package for testing various lib/helper functions in rhodecode
24 """
24 """
25
25
26 import datetime
26 import datetime
27 import string
27 import string
28 import mock
28 import mock
29 import pytest
29 import pytest
30
30
31 from rhodecode.tests import no_newline_id_generator
31 from rhodecode.tests import no_newline_id_generator
32 from rhodecode.tests.utils import run_test_concurrently
32 from rhodecode.tests.utils import run_test_concurrently
33 from rhodecode.lib.helpers import InitialsGravatar
33 from rhodecode.lib.helpers import InitialsGravatar
34
34
35 from rhodecode.lib.utils2 import AttributeDict
35 from rhodecode.lib.utils2 import AttributeDict
36 from rhodecode.model.db import Repository
36 from rhodecode.model.db import Repository
37
37
38
38
39 def _urls_for_proto(proto):
39 def _urls_for_proto(proto):
40 return [
40 return [
41 ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
41 ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
42 '%s://127.0.0.1' % proto),
42 '%s://127.0.0.1' % proto),
43 ('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
43 ('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
44 '%s://127.0.0.1' % proto),
44 '%s://127.0.0.1' % proto),
45 ('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
45 ('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
46 '%s://127.0.0.1' % proto),
46 '%s://127.0.0.1' % proto),
47 ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'],
47 ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'],
48 '%s://127.0.0.1:8080' % proto),
48 '%s://127.0.0.1:8080' % proto),
49 ('%s://domain.org' % proto, ['%s://' % proto, 'domain.org'],
49 ('%s://domain.org' % proto, ['%s://' % proto, 'domain.org'],
50 '%s://domain.org' % proto),
50 '%s://domain.org' % proto),
51 ('%s://user:pass@domain.org:8080' % proto,
51 ('%s://user:pass@domain.org:8080' % proto,
52 ['%s://' % proto, 'domain.org', '8080'],
52 ['%s://' % proto, 'domain.org', '8080'],
53 '%s://domain.org:8080' % proto),
53 '%s://domain.org:8080' % proto),
54 ]
54 ]
55
55
56 TEST_URLS = _urls_for_proto('http') + _urls_for_proto('https')
56 TEST_URLS = _urls_for_proto('http') + _urls_for_proto('https')
57
57
58
58
59 @pytest.mark.parametrize("test_url, expected, expected_creds", TEST_URLS)
59 @pytest.mark.parametrize("test_url, expected, expected_creds", TEST_URLS)
60 def test_uri_filter(test_url, expected, expected_creds):
60 def test_uri_filter(test_url, expected, expected_creds):
61 from rhodecode.lib.utils2 import uri_filter
61 from rhodecode.lib.utils2 import uri_filter
62 assert uri_filter(test_url) == expected
62 assert uri_filter(test_url) == expected
63
63
64
64
65 @pytest.mark.parametrize("test_url, expected, expected_creds", TEST_URLS)
65 @pytest.mark.parametrize("test_url, expected, expected_creds", TEST_URLS)
66 def test_credentials_filter(test_url, expected, expected_creds):
66 def test_credentials_filter(test_url, expected, expected_creds):
67 from rhodecode.lib.utils2 import credentials_filter
67 from rhodecode.lib.utils2 import credentials_filter
68 assert credentials_filter(test_url) == expected_creds
68 assert credentials_filter(test_url) == expected_creds
69
69
70
70
71 @pytest.mark.parametrize("str_bool, expected", [
71 @pytest.mark.parametrize("str_bool, expected", [
72 ('t', True),
72 ('t', True),
73 ('true', True),
73 ('true', True),
74 ('y', True),
74 ('y', True),
75 ('yes', True),
75 ('yes', True),
76 ('on', True),
76 ('on', True),
77 ('1', True),
77 ('1', True),
78 ('Y', True),
78 ('Y', True),
79 ('yeS', True),
79 ('yeS', True),
80 ('Y', True),
80 ('Y', True),
81 ('TRUE', True),
81 ('TRUE', True),
82 ('T', True),
82 ('T', True),
83 ('False', False),
83 ('False', False),
84 ('F', False),
84 ('F', False),
85 ('FALSE', False),
85 ('FALSE', False),
86 ('0', False),
86 ('0', False),
87 ('-1', False),
87 ('-1', False),
88 ('', False)
88 ('', False)
89 ])
89 ])
90 def test_str2bool(str_bool, expected):
90 def test_str2bool(str_bool, expected):
91 from rhodecode.lib.utils2 import str2bool
91 from rhodecode.lib.utils2 import str2bool
92 assert str2bool(str_bool) == expected
92 assert str2bool(str_bool) == expected
93
93
94
94
95 @pytest.mark.parametrize("text, expected", reduce(lambda a1,a2:a1+a2, [
95 @pytest.mark.parametrize("text, expected", reduce(lambda a1,a2:a1+a2, [
96 [
96 [
97 (pref+"", []),
97 (pref+"", []),
98 (pref+"Hi there @marcink", ['marcink']),
98 (pref+"Hi there @marcink", ['marcink']),
99 (pref+"Hi there @marcink and @bob", ['bob', 'marcink']),
99 (pref+"Hi there @marcink and @bob", ['bob', 'marcink']),
100 (pref+"Hi there @marcink\n", ['marcink']),
100 (pref+"Hi there @marcink\n", ['marcink']),
101 (pref+"Hi there @marcink and @bob\n", ['bob', 'marcink']),
101 (pref+"Hi there @marcink and @bob\n", ['bob', 'marcink']),
102 (pref+"Hi there marcin@rhodecode.com", []),
102 (pref+"Hi there marcin@rhodecode.com", []),
103 (pref+"Hi there @john.malcovic and @bob\n", ['bob', 'john.malcovic']),
103 (pref+"Hi there @john.malcovic and @bob\n", ['bob', 'john.malcovic']),
104 (pref+"This needs to be reviewed: (@marcink,@john)", ["john", "marcink"]),
104 (pref+"This needs to be reviewed: (@marcink,@john)", ["john", "marcink"]),
105 (pref+"This needs to be reviewed: (@marcink, @john)", ["john", "marcink"]),
105 (pref+"This needs to be reviewed: (@marcink, @john)", ["john", "marcink"]),
106 (pref+"This needs to be reviewed: [@marcink,@john]", ["john", "marcink"]),
106 (pref+"This needs to be reviewed: [@marcink,@john]", ["john", "marcink"]),
107 (pref+"This needs to be reviewed: (@marcink @john)", ["john", "marcink"]),
107 (pref+"This needs to be reviewed: (@marcink @john)", ["john", "marcink"]),
108 (pref+"@john @mary, please review", ["john", "mary"]),
108 (pref+"@john @mary, please review", ["john", "mary"]),
109 (pref+"@john,@mary, please review", ["john", "mary"]),
109 (pref+"@john,@mary, please review", ["john", "mary"]),
110 (pref+"Hej @123, @22john,@mary, please review", ['123', '22john', 'mary']),
110 (pref+"Hej @123, @22john,@mary, please review", ['123', '22john', 'mary']),
111 (pref+"@first hi there @marcink here's my email marcin@email.com "
111 (pref+"@first hi there @marcink here's my email marcin@email.com "
112 "@lukaszb check @one_more22 it pls @ ttwelve @D[] @one@two@three ", ['first', 'lukaszb', 'marcink', 'one', 'one_more22']),
112 "@lukaszb check @one_more22 it pls @ ttwelve @D[] @one@two@three ", ['first', 'lukaszb', 'marcink', 'one', 'one_more22']),
113 (pref+"@MARCIN @maRCiN @2one_more22 @john please see this http://org.pl", ['2one_more22', 'john', 'MARCIN', 'maRCiN']),
113 (pref+"@MARCIN @maRCiN @2one_more22 @john please see this http://org.pl", ['2one_more22', 'john', 'MARCIN', 'maRCiN']),
114 (pref+"@marian.user just do it @marco-polo and next extract @marco_polo", ['marco-polo', 'marco_polo', 'marian.user']),
114 (pref+"@marian.user just do it @marco-polo and next extract @marco_polo", ['marco-polo', 'marco_polo', 'marian.user']),
115 (pref+"user.dot hej ! not-needed maril@domain.org", []),
115 (pref+"user.dot hej ! not-needed maril@domain.org", []),
116 (pref+"\n@marcin", ['marcin']),
116 (pref+"\n@marcin", ['marcin']),
117 ]
117 ]
118 for pref in ['', '\n', 'hi !', '\t', '\n\n']]), ids=no_newline_id_generator)
118 for pref in ['', '\n', 'hi !', '\t', '\n\n']]), ids=no_newline_id_generator)
119 def test_mention_extractor(text, expected):
119 def test_mention_extractor(text, expected):
120 from rhodecode.lib.utils2 import extract_mentioned_users
120 from rhodecode.lib.utils2 import extract_mentioned_users
121 got = extract_mentioned_users(text)
121 got = extract_mentioned_users(text)
122 assert sorted(got, key=lambda x: x.lower()) == got
122 assert sorted(got, key=lambda x: x.lower()) == got
123 assert set(expected) == set(got)
123 assert set(expected) == set(got)
124
124
125 @pytest.mark.parametrize("age_args, expected, kw", [
125 @pytest.mark.parametrize("age_args, expected, kw", [
126 ({}, u'just now', {}),
126 ({}, u'just now', {}),
127 ({'seconds': -1}, u'1 second ago', {}),
127 ({'seconds': -1}, u'1 second ago', {}),
128 ({'seconds': -60 * 2}, u'2 minutes ago', {}),
128 ({'seconds': -60 * 2}, u'2 minutes ago', {}),
129 ({'hours': -1}, u'1 hour ago', {}),
129 ({'hours': -1}, u'1 hour ago', {}),
130 ({'hours': -24}, u'1 day ago', {}),
130 ({'hours': -24}, u'1 day ago', {}),
131 ({'hours': -24 * 5}, u'5 days ago', {}),
131 ({'hours': -24 * 5}, u'5 days ago', {}),
132 ({'months': -1}, u'1 month ago', {}),
132 ({'months': -1}, u'1 month ago', {}),
133 ({'months': -1, 'days': -2}, u'1 month and 2 days ago', {}),
133 ({'months': -1, 'days': -2}, u'1 month and 2 days ago', {}),
134 ({'years': -1, 'months': -1}, u'1 year and 1 month ago', {}),
134 ({'years': -1, 'months': -1}, u'1 year and 1 month ago', {}),
135 ({}, u'just now', {'short_format': True}),
135 ({}, u'just now', {'short_format': True}),
136 ({'seconds': -1}, u'1sec ago', {'short_format': True}),
136 ({'seconds': -1}, u'1sec ago', {'short_format': True}),
137 ({'seconds': -60 * 2}, u'2min ago', {'short_format': True}),
137 ({'seconds': -60 * 2}, u'2min ago', {'short_format': True}),
138 ({'hours': -1}, u'1h ago', {'short_format': True}),
138 ({'hours': -1}, u'1h ago', {'short_format': True}),
139 ({'hours': -24}, u'1d ago', {'short_format': True}),
139 ({'hours': -24}, u'1d ago', {'short_format': True}),
140 ({'hours': -24 * 5}, u'5d ago', {'short_format': True}),
140 ({'hours': -24 * 5}, u'5d ago', {'short_format': True}),
141 ({'months': -1}, u'1m ago', {'short_format': True}),
141 ({'months': -1}, u'1m ago', {'short_format': True}),
142 ({'months': -1, 'days': -2}, u'1m, 2d ago', {'short_format': True}),
142 ({'months': -1, 'days': -2}, u'1m, 2d ago', {'short_format': True}),
143 ({'years': -1, 'months': -1}, u'1y, 1m ago', {'short_format': True}),
143 ({'years': -1, 'months': -1}, u'1y, 1m ago', {'short_format': True}),
144 ])
144 ])
145 def test_age(age_args, expected, kw, pylonsapp):
145 def test_age(age_args, expected, kw, pylonsapp):
146 from rhodecode.lib.utils2 import age
146 from rhodecode.lib.utils2 import age
147 from dateutil import relativedelta
147 from dateutil import relativedelta
148 n = datetime.datetime(year=2012, month=5, day=17)
148 n = datetime.datetime(year=2012, month=5, day=17)
149 delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs)
149 delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs)
150
150
151 def translate(elem):
151 def translate(elem):
152 return elem.interpolate()
152 return elem.interpolate()
153
153
154 assert translate(age(n + delt(**age_args), now=n, **kw)) == expected
154 assert translate(age(n + delt(**age_args), now=n, **kw)) == expected
155
155
156
156
157 @pytest.mark.parametrize("age_args, expected, kw", [
157 @pytest.mark.parametrize("age_args, expected, kw", [
158 ({}, u'just now', {}),
158 ({}, u'just now', {}),
159 ({'seconds': 1}, u'in 1 second', {}),
159 ({'seconds': 1}, u'in 1 second', {}),
160 ({'seconds': 60 * 2}, u'in 2 minutes', {}),
160 ({'seconds': 60 * 2}, u'in 2 minutes', {}),
161 ({'hours': 1}, u'in 1 hour', {}),
161 ({'hours': 1}, u'in 1 hour', {}),
162 ({'hours': 24}, u'in 1 day', {}),
162 ({'hours': 24}, u'in 1 day', {}),
163 ({'hours': 24 * 5}, u'in 5 days', {}),
163 ({'hours': 24 * 5}, u'in 5 days', {}),
164 ({'months': 1}, u'in 1 month', {}),
164 ({'months': 1}, u'in 1 month', {}),
165 ({'months': 1, 'days': 1}, u'in 1 month and 1 day', {}),
165 ({'months': 1, 'days': 1}, u'in 1 month and 1 day', {}),
166 ({'years': 1, 'months': 1}, u'in 1 year and 1 month', {}),
166 ({'years': 1, 'months': 1}, u'in 1 year and 1 month', {}),
167 ({}, u'just now', {'short_format': True}),
167 ({}, u'just now', {'short_format': True}),
168 ({'seconds': 1}, u'in 1sec', {'short_format': True}),
168 ({'seconds': 1}, u'in 1sec', {'short_format': True}),
169 ({'seconds': 60 * 2}, u'in 2min', {'short_format': True}),
169 ({'seconds': 60 * 2}, u'in 2min', {'short_format': True}),
170 ({'hours': 1}, u'in 1h', {'short_format': True}),
170 ({'hours': 1}, u'in 1h', {'short_format': True}),
171 ({'hours': 24}, u'in 1d', {'short_format': True}),
171 ({'hours': 24}, u'in 1d', {'short_format': True}),
172 ({'hours': 24 * 5}, u'in 5d', {'short_format': True}),
172 ({'hours': 24 * 5}, u'in 5d', {'short_format': True}),
173 ({'months': 1}, u'in 1m', {'short_format': True}),
173 ({'months': 1}, u'in 1m', {'short_format': True}),
174 ({'months': 1, 'days': 1}, u'in 1m, 1d', {'short_format': True}),
174 ({'months': 1, 'days': 1}, u'in 1m, 1d', {'short_format': True}),
175 ({'years': 1, 'months': 1}, u'in 1y, 1m', {'short_format': True}),
175 ({'years': 1, 'months': 1}, u'in 1y, 1m', {'short_format': True}),
176 ])
176 ])
177 def test_age_in_future(age_args, expected, kw, pylonsapp):
177 def test_age_in_future(age_args, expected, kw, pylonsapp):
178 from rhodecode.lib.utils2 import age
178 from rhodecode.lib.utils2 import age
179 from dateutil import relativedelta
179 from dateutil import relativedelta
180 n = datetime.datetime(year=2012, month=5, day=17)
180 n = datetime.datetime(year=2012, month=5, day=17)
181 delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs)
181 delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs)
182
182
183 def translate(elem):
183 def translate(elem):
184 return elem.interpolate()
184 return elem.interpolate()
185
185
186 assert translate(age(n + delt(**age_args), now=n, **kw)) == expected
186 assert translate(age(n + delt(**age_args), now=n, **kw)) == expected
187
187
188
188
189 @pytest.mark.parametrize("sample, expected_tags", [
189 @pytest.mark.parametrize("sample, expected_tags", [
190 ((
190 ((
191 "hello world [stale]"
191 "hello world [stale]"
192 ),
192 ),
193 [
193 [
194 ('state', '[stale]'),
194 ('state', '[stale]'),
195 ]),
195 ]),
196 # entry
196 # entry
197 ((
197 ((
198 "hello world [v2.0.0] [v1.0.0]"
198 "hello world [v2.0.0] [v1.0.0]"
199 ),
199 ),
200 [
200 [
201 ('generic', '[v2.0.0]'),
201 ('generic', '[v2.0.0]'),
202 ('generic', '[v1.0.0]'),
202 ('generic', '[v1.0.0]'),
203 ]),
203 ]),
204 # entry
204 # entry
205 ((
205 ((
206 "he[ll]o wo[rl]d"
206 "he[ll]o wo[rl]d"
207 ),
207 ),
208 [
208 [
209 ('label', '[ll]'),
209 ('label', '[ll]'),
210 ('label', '[rl]'),
210 ('label', '[rl]'),
211 ]),
211 ]),
212 # entry
212 # entry
213 ((
213 ((
214 "hello world [stale]\n[featured]\n[stale] [dead] [dev]"
214 "hello world [stale]\n[featured]\n[stale] [dead] [dev]"
215 ),
215 ),
216 [
216 [
217 ('state', '[stale]'),
217 ('state', '[stale]'),
218 ('state', '[featured]'),
218 ('state', '[featured]'),
219 ('state', '[stale]'),
219 ('state', '[stale]'),
220 ('state', '[dead]'),
220 ('state', '[dead]'),
221 ('state', '[dev]'),
221 ('state', '[dev]'),
222 ]),
222 ]),
223 # entry
223 # entry
224 ((
224 ((
225 "hello world \n\n [stale] \n [url =&gt; [name](http://rc.com)]"
225 "hello world \n\n [stale] \n [url =&gt; [name](http://rc.com)]"
226 ),
226 ),
227 [
227 [
228 ('state', '[stale]'),
228 ('state', '[stale]'),
229 ('url', '[url =&gt; [name](http://rc.com)]'),
229 ('url', '[url =&gt; [name](http://rc.com)]'),
230 ]),
230 ]),
231 # entry
231 # entry
232 ((
232 ((
233 "hello pta[tag] gog [[]] [[] sda ero[or]d [me =&gt;>< sa]"
233 "hello pta[tag] gog [[]] [[] sda ero[or]d [me =&gt;>< sa]"
234 "[requires] [stale] [see<>=&gt;] [see =&gt; http://url.com]"
234 "[requires] [stale] [see<>=&gt;] [see =&gt; http://url.com]"
235 "[requires =&gt; url] [lang =&gt; python] [just a tag] "
235 "[requires =&gt; url] [lang =&gt; python] [just a tag] "
236 "<html_tag first='abc' attr=\"my.url?attr=&another=\"></html_tag>"
236 "<html_tag first='abc' attr=\"my.url?attr=&another=\"></html_tag>"
237 "[,d] [ =&gt; ULR ] [obsolete] [desc]]"
237 "[,d] [ =&gt; ULR ] [obsolete] [desc]]"
238 ),
238 ),
239 [
239 [
240 ('label', '[desc]'),
240 ('label', '[desc]'),
241 ('label', '[obsolete]'),
241 ('label', '[obsolete]'),
242 ('label', '[or]'),
242 ('label', '[or]'),
243 ('label', '[requires]'),
243 ('label', '[requires]'),
244 ('label', '[tag]'),
244 ('label', '[tag]'),
245 ('state', '[stale]'),
245 ('state', '[stale]'),
246 ('lang', '[lang =&gt; python]'),
246 ('lang', '[lang =&gt; python]'),
247 ('ref', '[requires =&gt; url]'),
247 ('ref', '[requires =&gt; url]'),
248 ('see', '[see =&gt; http://url.com]'),
248 ('see', '[see =&gt; http://url.com]'),
249
249
250 ]),
250 ]),
251
251
252 ], ids=no_newline_id_generator)
252 ], ids=no_newline_id_generator)
253 def test_metatag_extraction(sample, expected_tags):
253 def test_metatag_extraction(sample, expected_tags):
254 from rhodecode.lib.helpers import extract_metatags
254 from rhodecode.lib.helpers import extract_metatags
255 tags, value = extract_metatags(sample)
255 tags, value = extract_metatags(sample)
256 assert sorted(tags) == sorted(expected_tags)
256 assert sorted(tags) == sorted(expected_tags)
257
257
258
258
259 @pytest.mark.parametrize("tag_data, expected_html", [
259 @pytest.mark.parametrize("tag_data, expected_html", [
260
260
261 (('state', '[stable]'), '<div class="metatag" tag="state stable">stable</div>'),
261 (('state', '[stable]'), '<div class="metatag" tag="state stable">stable</div>'),
262 (('state', '[stale]'), '<div class="metatag" tag="state stale">stale</div>'),
262 (('state', '[stale]'), '<div class="metatag" tag="state stale">stale</div>'),
263 (('state', '[featured]'), '<div class="metatag" tag="state featured">featured</div>'),
263 (('state', '[featured]'), '<div class="metatag" tag="state featured">featured</div>'),
264 (('state', '[dev]'), '<div class="metatag" tag="state dev">dev</div>'),
264 (('state', '[dev]'), '<div class="metatag" tag="state dev">dev</div>'),
265 (('state', '[dead]'), '<div class="metatag" tag="state dead">dead</div>'),
265 (('state', '[dead]'), '<div class="metatag" tag="state dead">dead</div>'),
266
266
267 (('label', '[personal]'), '<div class="metatag" tag="label">personal</div>'),
267 (('label', '[personal]'), '<div class="metatag" tag="label">personal</div>'),
268 (('generic', '[v2.0.0]'), '<div class="metatag" tag="generic">v2.0.0</div>'),
268 (('generic', '[v2.0.0]'), '<div class="metatag" tag="generic">v2.0.0</div>'),
269
269
270 (('lang', '[lang =&gt; JavaScript]'), '<div class="metatag" tag="lang">JavaScript</div>'),
270 (('lang', '[lang =&gt; JavaScript]'), '<div class="metatag" tag="lang">JavaScript</div>'),
271 (('lang', '[lang =&gt; C++]'), '<div class="metatag" tag="lang">C++</div>'),
271 (('lang', '[lang =&gt; C++]'), '<div class="metatag" tag="lang">C++</div>'),
272 (('lang', '[lang =&gt; C#]'), '<div class="metatag" tag="lang">C#</div>'),
272 (('lang', '[lang =&gt; C#]'), '<div class="metatag" tag="lang">C#</div>'),
273 (('lang', '[lang =&gt; Delphi/Object]'), '<div class="metatag" tag="lang">Delphi/Object</div>'),
273 (('lang', '[lang =&gt; Delphi/Object]'), '<div class="metatag" tag="lang">Delphi/Object</div>'),
274 (('lang', '[lang =&gt; Objective-C]'), '<div class="metatag" tag="lang">Objective-C</div>'),
274 (('lang', '[lang =&gt; Objective-C]'), '<div class="metatag" tag="lang">Objective-C</div>'),
275 (('lang', '[lang =&gt; .NET]'), '<div class="metatag" tag="lang">.NET</div>'),
275 (('lang', '[lang =&gt; .NET]'), '<div class="metatag" tag="lang">.NET</div>'),
276
276
277 (('license', '[license =&gt; BSD 3-clause]'), '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/BSD 3-clause">BSD 3-clause</a></div>'),
277 (('license', '[license =&gt; BSD 3-clause]'), '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/BSD 3-clause">BSD 3-clause</a></div>'),
278 (('license', '[license =&gt; GPLv3]'), '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/GPLv3">GPLv3</a></div>'),
278 (('license', '[license =&gt; GPLv3]'), '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/GPLv3">GPLv3</a></div>'),
279 (('license', '[license =&gt; MIT]'), '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/MIT">MIT</a></div>'),
279 (('license', '[license =&gt; MIT]'), '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/MIT">MIT</a></div>'),
280 (('license', '[license =&gt; AGPLv3]'), '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/AGPLv3">AGPLv3</a></div>'),
280 (('license', '[license =&gt; AGPLv3]'), '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/AGPLv3">AGPLv3</a></div>'),
281
281
282 (('ref', '[requires =&gt; RepoName]'), '<div class="metatag" tag="ref requires">requires: <a href="/RepoName">RepoName</a></div>'),
282 (('ref', '[requires =&gt; RepoName]'), '<div class="metatag" tag="ref requires">requires: <a href="/RepoName">RepoName</a></div>'),
283 (('ref', '[recommends =&gt; GroupName]'), '<div class="metatag" tag="ref recommends">recommends: <a href="/GroupName">GroupName</a></div>'),
283 (('ref', '[recommends =&gt; GroupName]'), '<div class="metatag" tag="ref recommends">recommends: <a href="/GroupName">GroupName</a></div>'),
284 (('ref', '[conflicts =&gt; SomeName]'), '<div class="metatag" tag="ref conflicts">conflicts: <a href="/SomeName">SomeName</a></div>'),
284 (('ref', '[conflicts =&gt; SomeName]'), '<div class="metatag" tag="ref conflicts">conflicts: <a href="/SomeName">SomeName</a></div>'),
285 (('ref', '[base =&gt; SomeName]'), '<div class="metatag" tag="ref base">base: <a href="/SomeName">SomeName</a></div>'),
285 (('ref', '[base =&gt; SomeName]'), '<div class="metatag" tag="ref base">base: <a href="/SomeName">SomeName</a></div>'),
286
286
287 (('see', '[see =&gt; http://rhodecode.com]'), '<div class="metatag" tag="see">see: http://rhodecode.com </div>'),
287 (('see', '[see =&gt; http://rhodecode.com]'), '<div class="metatag" tag="see">see: http://rhodecode.com </div>'),
288
288
289 (('url', '[url =&gt; [linkName](https://rhodecode.com)]'), '<div class="metatag" tag="url"> <a href="https://rhodecode.com">linkName</a> </div>'),
289 (('url', '[url =&gt; [linkName](https://rhodecode.com)]'), '<div class="metatag" tag="url"> <a href="https://rhodecode.com">linkName</a> </div>'),
290 (('url', '[url =&gt; [example link](https://rhodecode.com)]'), '<div class="metatag" tag="url"> <a href="https://rhodecode.com">example link</a> </div>'),
290 (('url', '[url =&gt; [example link](https://rhodecode.com)]'), '<div class="metatag" tag="url"> <a href="https://rhodecode.com">example link</a> </div>'),
291 (('url', '[url =&gt; [v1.0.0](https://rhodecode.com)]'), '<div class="metatag" tag="url"> <a href="https://rhodecode.com">v1.0.0</a> </div>'),
291 (('url', '[url =&gt; [v1.0.0](https://rhodecode.com)]'), '<div class="metatag" tag="url"> <a href="https://rhodecode.com">v1.0.0</a> </div>'),
292
292
293 ])
293 ])
294 def test_metatags_stylize(tag_data, expected_html):
294 def test_metatags_stylize(tag_data, expected_html):
295 from rhodecode.lib.helpers import style_metatag
295 from rhodecode.lib.helpers import style_metatag
296 tag_type,value = tag_data
296 tag_type,value = tag_data
297 assert style_metatag(tag_type, value) == expected_html
297 assert style_metatag(tag_type, value) == expected_html
298
298
299
299
300 @pytest.mark.parametrize("tmpl_url, email, expected", [
300 @pytest.mark.parametrize("tmpl_url, email, expected", [
301 ('http://test.com/{email}', 'test@foo.com', 'http://test.com/test@foo.com'),
301 ('http://test.com/{email}', 'test@foo.com', 'http://test.com/test@foo.com'),
302
302
303 ('http://test.com/{md5email}', 'test@foo.com', 'http://test.com/3cb7232fcc48743000cb86d0d5022bd9'),
303 ('http://test.com/{md5email}', 'test@foo.com', 'http://test.com/3cb7232fcc48743000cb86d0d5022bd9'),
304 ('http://test.com/{md5email}', 'testΔ…Δ‡@foo.com', 'http://test.com/978debb907a3c55cd741872ab293ef30'),
304 ('http://test.com/{md5email}', 'testΔ…Δ‡@foo.com', 'http://test.com/978debb907a3c55cd741872ab293ef30'),
305
305
306 ('http://testX.com/{md5email}?s={size}', 'test@foo.com', 'http://testX.com/3cb7232fcc48743000cb86d0d5022bd9?s=24'),
306 ('http://testX.com/{md5email}?s={size}', 'test@foo.com', 'http://testX.com/3cb7232fcc48743000cb86d0d5022bd9?s=24'),
307 ('http://testX.com/{md5email}?s={size}', 'testΔ…Δ‡@foo.com', 'http://testX.com/978debb907a3c55cd741872ab293ef30?s=24'),
307 ('http://testX.com/{md5email}?s={size}', 'testΔ…Δ‡@foo.com', 'http://testX.com/978debb907a3c55cd741872ab293ef30?s=24'),
308
308
309 ('{scheme}://{netloc}/{md5email}/{size}', 'test@foo.com', 'https://server.com/3cb7232fcc48743000cb86d0d5022bd9/24'),
309 ('{scheme}://{netloc}/{md5email}/{size}', 'test@foo.com', 'https://server.com/3cb7232fcc48743000cb86d0d5022bd9/24'),
310 ('{scheme}://{netloc}/{md5email}/{size}', 'testΔ…Δ‡@foo.com', 'https://server.com/978debb907a3c55cd741872ab293ef30/24'),
310 ('{scheme}://{netloc}/{md5email}/{size}', 'testΔ…Δ‡@foo.com', 'https://server.com/978debb907a3c55cd741872ab293ef30/24'),
311
311
312 ('http://test.com/{email}', 'testΔ…Δ‡@foo.com', 'http://test.com/testΔ…Δ‡@foo.com'),
312 ('http://test.com/{email}', 'testΔ…Δ‡@foo.com', 'http://test.com/testΔ…Δ‡@foo.com'),
313 ('http://test.com/{email}?size={size}', 'test@foo.com', 'http://test.com/test@foo.com?size=24'),
313 ('http://test.com/{email}?size={size}', 'test@foo.com', 'http://test.com/test@foo.com?size=24'),
314 ('http://test.com/{email}?size={size}', 'testΔ…Δ‡@foo.com', 'http://test.com/testΔ…Δ‡@foo.com?size=24'),
314 ('http://test.com/{email}?size={size}', 'testΔ…Δ‡@foo.com', 'http://test.com/testΔ…Δ‡@foo.com?size=24'),
315 ])
315 ])
316 def test_gravatar_url_builder(tmpl_url, email, expected, request_stub):
316 def test_gravatar_url_builder(tmpl_url, email, expected, request_stub):
317 from rhodecode.lib.helpers import gravatar_url
317 from rhodecode.lib.helpers import gravatar_url
318
318
319 # mock pyramid.threadlocals
320 def fake_get_current_request():
321 request_stub.scheme = 'https'
322 request_stub.host = 'server.com'
323 return request_stub
324
325 # mock pylons.tmpl_context
326 def fake_tmpl_context(_url):
319 def fake_tmpl_context(_url):
327 _c = AttributeDict()
320 _c = AttributeDict()
328 _c.visual = AttributeDict()
321 _c.visual = AttributeDict()
329 _c.visual.use_gravatar = True
322 _c.visual.use_gravatar = True
330 _c.visual.gravatar_url = _url
323 _c.visual.gravatar_url = _url
324 return _c
331
325
332 return _c
326 # mock pyramid.threadlocals
327 def fake_get_current_request():
328 request_stub.scheme = 'https'
329 request_stub.host = 'server.com'
330
331 request_stub._call_context = fake_tmpl_context(tmpl_url)
332 return request_stub
333
333
334 with mock.patch('rhodecode.lib.helpers.get_current_request',
334 with mock.patch('rhodecode.lib.helpers.get_current_request',
335 fake_get_current_request):
335 fake_get_current_request):
336 fake = fake_tmpl_context(_url=tmpl_url)
336
337 with mock.patch('pylons.tmpl_context', fake):
338 grav = gravatar_url(email_address=email, size=24)
337 grav = gravatar_url(email_address=email, size=24)
339 assert grav == expected
338 assert grav == expected
340
339
341
340
342 @pytest.mark.parametrize(
341 @pytest.mark.parametrize(
343 "email, first_name, last_name, expected_initials, expected_color", [
342 "email, first_name, last_name, expected_initials, expected_color", [
344
343
345 ('test@rhodecode.com', '', '', 'TR', '#8a994d'),
344 ('test@rhodecode.com', '', '', 'TR', '#8a994d'),
346 ('marcin.kuzminski@rhodecode.com', '', '', 'MK', '#6559b3'),
345 ('marcin.kuzminski@rhodecode.com', '', '', 'MK', '#6559b3'),
347 # special cases of email
346 # special cases of email
348 ('john.van.dam@rhodecode.com', '', '', 'JD', '#526600'),
347 ('john.van.dam@rhodecode.com', '', '', 'JD', '#526600'),
349 ('Guido.van.Rossum@rhodecode.com', '', '', 'GR', '#990052'),
348 ('Guido.van.Rossum@rhodecode.com', '', '', 'GR', '#990052'),
350 ('Guido.van.Rossum@rhodecode.com', 'Guido', 'Van Rossum', 'GR', '#990052'),
349 ('Guido.van.Rossum@rhodecode.com', 'Guido', 'Van Rossum', 'GR', '#990052'),
351
350
352 ('rhodecode+Guido.van.Rossum@rhodecode.com', '', '', 'RR', '#46598c'),
351 ('rhodecode+Guido.van.Rossum@rhodecode.com', '', '', 'RR', '#46598c'),
353 ('pclouds@rhodecode.com', 'Nguyα»…n ThΓ‘i', 'Tgọc Duy', 'ND', '#665200'),
352 ('pclouds@rhodecode.com', 'Nguyα»…n ThΓ‘i', 'Tgọc Duy', 'ND', '#665200'),
354
353
355 ('john-brown@foo.com', '', '', 'JF', '#73006b'),
354 ('john-brown@foo.com', '', '', 'JF', '#73006b'),
356 ('admin@rhodecode.com', 'Marcin', 'Kuzminski', 'MK', '#104036'),
355 ('admin@rhodecode.com', 'Marcin', 'Kuzminski', 'MK', '#104036'),
357 # partials
356 # partials
358 ('admin@rhodecode.com', 'Marcin', '', 'MR', '#104036'), # fn+email
357 ('admin@rhodecode.com', 'Marcin', '', 'MR', '#104036'), # fn+email
359 ('admin@rhodecode.com', '', 'Kuzminski', 'AK', '#104036'), # em+ln
358 ('admin@rhodecode.com', '', 'Kuzminski', 'AK', '#104036'), # em+ln
360 # non-ascii
359 # non-ascii
361 ('admin@rhodecode.com', 'Marcin', 'Śuzminski', 'MS', '#104036'),
360 ('admin@rhodecode.com', 'Marcin', 'Śuzminski', 'MS', '#104036'),
362 ('marcin.Ε›uzminski@rhodecode.com', '', '', 'MS', '#73000f'),
361 ('marcin.Ε›uzminski@rhodecode.com', '', '', 'MS', '#73000f'),
363
362
364 # special cases, LDAP can provide those...
363 # special cases, LDAP can provide those...
365 ('admin@', 'Marcin', 'Śuzminski', 'MS', '#aa00ff'),
364 ('admin@', 'Marcin', 'Śuzminski', 'MS', '#aa00ff'),
366 ('marcin.Ε›uzminski', '', '', 'MS', '#402020'),
365 ('marcin.Ε›uzminski', '', '', 'MS', '#402020'),
367 ('null', '', '', 'NL', '#8c4646'),
366 ('null', '', '', 'NL', '#8c4646'),
368 ('some.@abc.com', 'some', '', 'SA', '#664e33')
367 ('some.@abc.com', 'some', '', 'SA', '#664e33')
369 ])
368 ])
370 def test_initials_gravatar_pick_of_initials_and_color_algo(
369 def test_initials_gravatar_pick_of_initials_and_color_algo(
371 email, first_name, last_name, expected_initials, expected_color):
370 email, first_name, last_name, expected_initials, expected_color):
372 instance = InitialsGravatar(email, first_name, last_name)
371 instance = InitialsGravatar(email, first_name, last_name)
373 assert instance.get_initials() == expected_initials
372 assert instance.get_initials() == expected_initials
374 assert instance.str2color(email) == expected_color
373 assert instance.str2color(email) == expected_color
375
374
376
375
377 def test_initials_gravatar_mapping_algo():
376 def test_initials_gravatar_mapping_algo():
378 pos = set()
377 pos = set()
379 instance = InitialsGravatar('', '', '')
378 instance = InitialsGravatar('', '', '')
380 iterations = 0
379 iterations = 0
381
380
382 variations = []
381 variations = []
383 for letter1 in string.ascii_letters:
382 for letter1 in string.ascii_letters:
384 for letter2 in string.ascii_letters[::-1][:10]:
383 for letter2 in string.ascii_letters[::-1][:10]:
385 for letter3 in string.ascii_letters[:10]:
384 for letter3 in string.ascii_letters[:10]:
386 variations.append(
385 variations.append(
387 '%s@rhodecode.com' % (letter1+letter2+letter3))
386 '%s@rhodecode.com' % (letter1+letter2+letter3))
388
387
389 max_variations = 4096
388 max_variations = 4096
390 for email in variations[:max_variations]:
389 for email in variations[:max_variations]:
391 iterations += 1
390 iterations += 1
392 pos.add(
391 pos.add(
393 instance.pick_color_bank_index(email,
392 instance.pick_color_bank_index(email,
394 instance.get_color_bank()))
393 instance.get_color_bank()))
395
394
396 # we assume that we have match all 256 possible positions,
395 # we assume that we have match all 256 possible positions,
397 # in reasonable amount of different email addresses
396 # in reasonable amount of different email addresses
398 assert len(pos) == 256
397 assert len(pos) == 256
399 assert iterations == max_variations
398 assert iterations == max_variations
400
399
401
400
402 @pytest.mark.parametrize("tmpl, repo_name, overrides, prefix, expected", [
401 @pytest.mark.parametrize("tmpl, repo_name, overrides, prefix, expected", [
403 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {}, '', 'http://vps1:8000/group/repo1'),
402 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {}, '', 'http://vps1:8000/group/repo1'),
404 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'marcink'}, '', 'http://marcink@vps1:8000/group/repo1'),
403 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'marcink'}, '', 'http://marcink@vps1:8000/group/repo1'),
405 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {}, '/rc', 'http://vps1:8000/rc/group/repo1'),
404 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {}, '/rc', 'http://vps1:8000/rc/group/repo1'),
406 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'user'}, '/rc', 'http://user@vps1:8000/rc/group/repo1'),
405 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'user'}, '/rc', 'http://user@vps1:8000/rc/group/repo1'),
407 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'marcink'}, '/rc', 'http://marcink@vps1:8000/rc/group/repo1'),
406 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'marcink'}, '/rc', 'http://marcink@vps1:8000/rc/group/repo1'),
408 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'user'}, '/rc/', 'http://user@vps1:8000/rc/group/repo1'),
407 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'user'}, '/rc/', 'http://user@vps1:8000/rc/group/repo1'),
409 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'marcink'}, '/rc/', 'http://marcink@vps1:8000/rc/group/repo1'),
408 (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'marcink'}, '/rc/', 'http://marcink@vps1:8000/rc/group/repo1'),
410 ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', {}, '', 'http://vps1:8000/_23'),
409 ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', {}, '', 'http://vps1:8000/_23'),
411 ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', {'user': 'marcink'}, '', 'http://marcink@vps1:8000/_23'),
410 ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', {'user': 'marcink'}, '', 'http://marcink@vps1:8000/_23'),
412 ('http://{user}@{netloc}/_{repoid}', 'group/repo1', {'user': 'marcink'}, '', 'http://marcink@vps1:8000/_23'),
411 ('http://{user}@{netloc}/_{repoid}', 'group/repo1', {'user': 'marcink'}, '', 'http://marcink@vps1:8000/_23'),
413 ('http://{netloc}/_{repoid}', 'group/repo1', {'user': 'marcink'}, '', 'http://vps1:8000/_23'),
412 ('http://{netloc}/_{repoid}', 'group/repo1', {'user': 'marcink'}, '', 'http://vps1:8000/_23'),
414 ('https://{user}@proxy1.server.com/{repo}', 'group/repo1', {'user': 'marcink'}, '', 'https://marcink@proxy1.server.com/group/repo1'),
413 ('https://{user}@proxy1.server.com/{repo}', 'group/repo1', {'user': 'marcink'}, '', 'https://marcink@proxy1.server.com/group/repo1'),
415 ('https://{user}@proxy1.server.com/{repo}', 'group/repo1', {}, '', 'https://proxy1.server.com/group/repo1'),
414 ('https://{user}@proxy1.server.com/{repo}', 'group/repo1', {}, '', 'https://proxy1.server.com/group/repo1'),
416 ('https://proxy1.server.com/{user}/{repo}', 'group/repo1', {'user': 'marcink'}, '', 'https://proxy1.server.com/marcink/group/repo1'),
415 ('https://proxy1.server.com/{user}/{repo}', 'group/repo1', {'user': 'marcink'}, '', 'https://proxy1.server.com/marcink/group/repo1'),
417 ])
416 ])
418 def test_clone_url_generator(tmpl, repo_name, overrides, prefix, expected):
417 def test_clone_url_generator(tmpl, repo_name, overrides, prefix, expected):
419 from rhodecode.lib.utils2 import get_clone_url
418 from rhodecode.lib.utils2 import get_clone_url
420
419
421 class RequestStub(object):
420 class RequestStub(object):
422 def request_url(self, name):
421 def request_url(self, name):
423 return 'http://vps1:8000' + prefix
422 return 'http://vps1:8000' + prefix
424
423
425 def route_url(self, name):
424 def route_url(self, name):
426 return self.request_url(name)
425 return self.request_url(name)
427
426
428 clone_url = get_clone_url(
427 clone_url = get_clone_url(
429 request=RequestStub(),
428 request=RequestStub(),
430 uri_tmpl=tmpl,
429 uri_tmpl=tmpl,
431 repo_name=repo_name, repo_id=23, **overrides)
430 repo_name=repo_name, repo_id=23, **overrides)
432 assert clone_url == expected
431 assert clone_url == expected
433
432
434
433
435 def _quick_url(text, tmpl="""<a class="revision-link" href="%s">%s</a>""", url_=None):
434 def _quick_url(text, tmpl="""<a class="revision-link" href="%s">%s</a>""", url_=None):
436 """
435 """
437 Changes `some text url[foo]` => `some text <a href="/">foo</a>
436 Changes `some text url[foo]` => `some text <a href="/">foo</a>
438
437
439 :param text:
438 :param text:
440 """
439 """
441 import re
440 import re
442 # quickly change expected url[] into a link
441 # quickly change expected url[] into a link
443 URL_PAT = re.compile(r'(?:url\[)(.+?)(?:\])')
442 URL_PAT = re.compile(r'(?:url\[)(.+?)(?:\])')
444
443
445 def url_func(match_obj):
444 def url_func(match_obj):
446 _url = match_obj.groups()[0]
445 _url = match_obj.groups()[0]
447 return tmpl % (url_ or '/some-url', _url)
446 return tmpl % (url_ or '/some-url', _url)
448 return URL_PAT.sub(url_func, text)
447 return URL_PAT.sub(url_func, text)
449
448
450
449
451 @pytest.mark.parametrize("sample, expected", [
450 @pytest.mark.parametrize("sample, expected", [
452 ("",
451 ("",
453 ""),
452 ""),
454 ("git-svn-id: https://svn.apache.org/repos/asf/libcloud/trunk@1441655 13f79535-47bb-0310-9956-ffa450edef68",
453 ("git-svn-id: https://svn.apache.org/repos/asf/libcloud/trunk@1441655 13f79535-47bb-0310-9956-ffa450edef68",
455 "git-svn-id: https://svn.apache.org/repos/asf/libcloud/trunk@1441655 13f79535-47bb-0310-9956-ffa450edef68"),
454 "git-svn-id: https://svn.apache.org/repos/asf/libcloud/trunk@1441655 13f79535-47bb-0310-9956-ffa450edef68"),
456 ("from rev 000000000000",
455 ("from rev 000000000000",
457 "from rev url[000000000000]"),
456 "from rev url[000000000000]"),
458 ("from rev 000000000000123123 also rev 000000000000",
457 ("from rev 000000000000123123 also rev 000000000000",
459 "from rev url[000000000000123123] also rev url[000000000000]"),
458 "from rev url[000000000000123123] also rev url[000000000000]"),
460 ("this should-000 00",
459 ("this should-000 00",
461 "this should-000 00"),
460 "this should-000 00"),
462 ("longtextffffffffff rev 123123123123",
461 ("longtextffffffffff rev 123123123123",
463 "longtextffffffffff rev url[123123123123]"),
462 "longtextffffffffff rev url[123123123123]"),
464 ("rev ffffffffffffffffffffffffffffffffffffffffffffffffff",
463 ("rev ffffffffffffffffffffffffffffffffffffffffffffffffff",
465 "rev ffffffffffffffffffffffffffffffffffffffffffffffffff"),
464 "rev ffffffffffffffffffffffffffffffffffffffffffffffffff"),
466 ("ffffffffffff some text traalaa",
465 ("ffffffffffff some text traalaa",
467 "url[ffffffffffff] some text traalaa"),
466 "url[ffffffffffff] some text traalaa"),
468 ("""Multi line
467 ("""Multi line
469 123123123123
468 123123123123
470 some text 123123123123
469 some text 123123123123
471 sometimes !
470 sometimes !
472 """,
471 """,
473 """Multi line
472 """Multi line
474 url[123123123123]
473 url[123123123123]
475 some text url[123123123123]
474 some text url[123123123123]
476 sometimes !
475 sometimes !
477 """)
476 """)
478 ], ids=no_newline_id_generator)
477 ], ids=no_newline_id_generator)
479 def test_urlify_commits(sample, expected):
478 def test_urlify_commits(sample, expected):
480 def fake_url(self, *args, **kwargs):
479 def fake_url(self, *args, **kwargs):
481 return '/some-url'
480 return '/some-url'
482
481
483 expected = _quick_url(expected)
482 expected = _quick_url(expected)
484
483
485 with mock.patch('rhodecode.lib.helpers.route_url', fake_url):
484 with mock.patch('rhodecode.lib.helpers.route_url', fake_url):
486 from rhodecode.lib.helpers import urlify_commits
485 from rhodecode.lib.helpers import urlify_commits
487 assert urlify_commits(sample, 'repo_name') == expected
486 assert urlify_commits(sample, 'repo_name') == expected
488
487
489
488
490 @pytest.mark.parametrize("sample, expected, url_", [
489 @pytest.mark.parametrize("sample, expected, url_", [
491 ("",
490 ("",
492 "",
491 "",
493 ""),
492 ""),
494 ("https://svn.apache.org/repos",
493 ("https://svn.apache.org/repos",
495 "url[https://svn.apache.org/repos]",
494 "url[https://svn.apache.org/repos]",
496 "https://svn.apache.org/repos"),
495 "https://svn.apache.org/repos"),
497 ("http://svn.apache.org/repos",
496 ("http://svn.apache.org/repos",
498 "url[http://svn.apache.org/repos]",
497 "url[http://svn.apache.org/repos]",
499 "http://svn.apache.org/repos"),
498 "http://svn.apache.org/repos"),
500 ("from rev a also rev http://google.com",
499 ("from rev a also rev http://google.com",
501 "from rev a also rev url[http://google.com]",
500 "from rev a also rev url[http://google.com]",
502 "http://google.com"),
501 "http://google.com"),
503 ("""Multi line
502 ("""Multi line
504 https://foo.bar.com
503 https://foo.bar.com
505 some text lalala""",
504 some text lalala""",
506 """Multi line
505 """Multi line
507 url[https://foo.bar.com]
506 url[https://foo.bar.com]
508 some text lalala""",
507 some text lalala""",
509 "https://foo.bar.com")
508 "https://foo.bar.com")
510 ], ids=no_newline_id_generator)
509 ], ids=no_newline_id_generator)
511 def test_urlify_test(sample, expected, url_):
510 def test_urlify_test(sample, expected, url_):
512 from rhodecode.lib.helpers import urlify_text
511 from rhodecode.lib.helpers import urlify_text
513 expected = _quick_url(expected, tmpl="""<a href="%s">%s</a>""", url_=url_)
512 expected = _quick_url(expected, tmpl="""<a href="%s">%s</a>""", url_=url_)
514 assert urlify_text(sample) == expected
513 assert urlify_text(sample) == expected
515
514
516
515
517 @pytest.mark.parametrize("test, expected", [
516 @pytest.mark.parametrize("test, expected", [
518 ("", None),
517 ("", None),
519 ("/_2", '2'),
518 ("/_2", '2'),
520 ("_2", '2'),
519 ("_2", '2'),
521 ("/_2/", '2'),
520 ("/_2/", '2'),
522 ("_2/", '2'),
521 ("_2/", '2'),
523
522
524 ("/_21", '21'),
523 ("/_21", '21'),
525 ("_21", '21'),
524 ("_21", '21'),
526 ("/_21/", '21'),
525 ("/_21/", '21'),
527 ("_21/", '21'),
526 ("_21/", '21'),
528
527
529 ("/_21/foobar", '21'),
528 ("/_21/foobar", '21'),
530 ("_21/121", '21'),
529 ("_21/121", '21'),
531 ("/_21/_12", '21'),
530 ("/_21/_12", '21'),
532 ("_21/rc/foo", '21'),
531 ("_21/rc/foo", '21'),
533
532
534 ])
533 ])
535 def test_get_repo_by_id(test, expected):
534 def test_get_repo_by_id(test, expected):
536 from rhodecode.model.repo import RepoModel
535 from rhodecode.model.repo import RepoModel
537 _test = RepoModel()._extract_id_from_repo_name(test)
536 _test = RepoModel()._extract_id_from_repo_name(test)
538 assert _test == expected
537 assert _test == expected
539
538
540
539
541 @pytest.mark.parametrize("test_repo_name, repo_type", [
540 @pytest.mark.parametrize("test_repo_name, repo_type", [
542 ("test_repo_1", None),
541 ("test_repo_1", None),
543 ("repo_group/foobar", None),
542 ("repo_group/foobar", None),
544 ("test_non_asci_Δ…Δ‡Δ™", None),
543 ("test_non_asci_Δ…Δ‡Δ™", None),
545 (u"test_non_asci_unicode_Δ…Δ‡Δ™", None),
544 (u"test_non_asci_unicode_Δ…Δ‡Δ™", None),
546 ])
545 ])
547 def test_invalidation_context(pylonsapp, test_repo_name, repo_type):
546 def test_invalidation_context(pylonsapp, test_repo_name, repo_type):
548 from beaker.cache import cache_region
547 from beaker.cache import cache_region
549 from rhodecode.lib import caches
548 from rhodecode.lib import caches
550 from rhodecode.model.db import CacheKey
549 from rhodecode.model.db import CacheKey
551
550
552 @cache_region('long_term')
551 @cache_region('long_term')
553 def _dummy_func(cache_key):
552 def _dummy_func(cache_key):
554 return 'result'
553 return 'result'
555
554
556 invalidator_context = CacheKey.repo_context_cache(
555 invalidator_context = CacheKey.repo_context_cache(
557 _dummy_func, test_repo_name, 'repo')
556 _dummy_func, test_repo_name, 'repo')
558
557
559 with invalidator_context as context:
558 with invalidator_context as context:
560 invalidated = context.invalidate()
559 invalidated = context.invalidate()
561 result = context.compute()
560 result = context.compute()
562
561
563 assert invalidated == True
562 assert invalidated == True
564 assert 'result' == result
563 assert 'result' == result
565 assert isinstance(context, caches.FreshRegionCache)
564 assert isinstance(context, caches.FreshRegionCache)
566
565
567 assert 'InvalidationContext' in repr(invalidator_context)
566 assert 'InvalidationContext' in repr(invalidator_context)
568
567
569 with invalidator_context as context:
568 with invalidator_context as context:
570 context.invalidate()
569 context.invalidate()
571 result = context.compute()
570 result = context.compute()
572
571
573 assert 'result' == result
572 assert 'result' == result
574 assert isinstance(context, caches.ActiveRegionCache)
573 assert isinstance(context, caches.ActiveRegionCache)
575
574
576
575
577 def test_invalidation_context_exception_in_compute(pylonsapp):
576 def test_invalidation_context_exception_in_compute(pylonsapp):
578 from rhodecode.model.db import CacheKey
577 from rhodecode.model.db import CacheKey
579 from beaker.cache import cache_region
578 from beaker.cache import cache_region
580
579
581 @cache_region('long_term')
580 @cache_region('long_term')
582 def _dummy_func(cache_key):
581 def _dummy_func(cache_key):
583 # this causes error since it doesn't get any params
582 # this causes error since it doesn't get any params
584 raise Exception('ups')
583 raise Exception('ups')
585
584
586 invalidator_context = CacheKey.repo_context_cache(
585 invalidator_context = CacheKey.repo_context_cache(
587 _dummy_func, 'test_repo_2', 'repo')
586 _dummy_func, 'test_repo_2', 'repo')
588
587
589 with pytest.raises(Exception):
588 with pytest.raises(Exception):
590 with invalidator_context as context:
589 with invalidator_context as context:
591 context.invalidate()
590 context.invalidate()
592 context.compute()
591 context.compute()
593
592
594
593
595 @pytest.mark.parametrize('execution_number', range(5))
594 @pytest.mark.parametrize('execution_number', range(5))
596 def test_cache_invalidation_race_condition(execution_number, pylonsapp):
595 def test_cache_invalidation_race_condition(execution_number, pylonsapp):
597 import time
596 import time
598 from beaker.cache import cache_region
597 from beaker.cache import cache_region
599 from rhodecode.model.db import CacheKey
598 from rhodecode.model.db import CacheKey
600
599
601 if CacheKey.metadata.bind.url.get_backend_name() == "mysql":
600 if CacheKey.metadata.bind.url.get_backend_name() == "mysql":
602 reason = (
601 reason = (
603 'Fails on MariaDB due to some locking issues. Investigation'
602 'Fails on MariaDB due to some locking issues. Investigation'
604 ' needed')
603 ' needed')
605 pytest.xfail(reason=reason)
604 pytest.xfail(reason=reason)
606
605
607 @run_test_concurrently(25)
606 @run_test_concurrently(25)
608 def test_create_and_delete_cache_keys():
607 def test_create_and_delete_cache_keys():
609 time.sleep(0.2)
608 time.sleep(0.2)
610
609
611 @cache_region('long_term')
610 @cache_region('long_term')
612 def _dummy_func(cache_key):
611 def _dummy_func(cache_key):
613 return 'result'
612 return 'result'
614
613
615 invalidator_context = CacheKey.repo_context_cache(
614 invalidator_context = CacheKey.repo_context_cache(
616 _dummy_func, 'test_repo_1', 'repo')
615 _dummy_func, 'test_repo_1', 'repo')
617
616
618 with invalidator_context as context:
617 with invalidator_context as context:
619 context.invalidate()
618 context.invalidate()
620 context.compute()
619 context.compute()
621
620
622 CacheKey.set_invalidate('test_repo_1', delete=True)
621 CacheKey.set_invalidate('test_repo_1', delete=True)
623
622
624 test_create_and_delete_cache_keys()
623 test_create_and_delete_cache_keys()
General Comments 0
You need to be logged in to leave comments. Login now