##// END OF EJS Templates
tests: use more random ports created at start of rc-web server to stabilize the tests.
marcink -
r2614:803cf0e0 default
parent child Browse files
Show More
@@ -1,265 +1,269 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2018 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 py.test config for test suite for making push/pull operations.
22 py.test config for test suite for making push/pull operations.
23
23
24 .. important::
24 .. important::
25
25
26 You must have git >= 1.8.5 for tests to work fine. With 68b939b git started
26 You must have git >= 1.8.5 for tests to work fine. With 68b939b git started
27 to redirect things to stderr instead of stdout.
27 to redirect things to stderr instead of stdout.
28 """
28 """
29
29
30 import os
30 import os
31 import tempfile
31 import tempfile
32 import textwrap
32 import textwrap
33 import pytest
33 import pytest
34
34
35 from rhodecode import events
35 from rhodecode import events
36 from rhodecode.model.db import Integration
36 from rhodecode.model.db import Integration
37 from rhodecode.model.integration import IntegrationModel
37 from rhodecode.model.integration import IntegrationModel
38 from rhodecode.model.db import Repository
38 from rhodecode.model.db import Repository
39 from rhodecode.model.meta import Session
39 from rhodecode.model.meta import Session
40 from rhodecode.model.settings import SettingsModel
40 from rhodecode.model.settings import SettingsModel
41 from rhodecode.integrations.types.webhook import WebhookIntegrationType
41 from rhodecode.integrations.types.webhook import WebhookIntegrationType
42
42
43 from rhodecode.tests import GIT_REPO, HG_REPO
43 from rhodecode.tests import GIT_REPO, HG_REPO
44 from rhodecode.tests.fixture import Fixture
44 from rhodecode.tests.fixture import Fixture
45 from rhodecode.tests.server_utils import RcWebServer
45 from rhodecode.tests.server_utils import RcWebServer
46
46
47 REPO_GROUP = 'a_repo_group'
47 REPO_GROUP = 'a_repo_group'
48 HG_REPO_WITH_GROUP = '%s/%s' % (REPO_GROUP, HG_REPO)
48 HG_REPO_WITH_GROUP = '%s/%s' % (REPO_GROUP, HG_REPO)
49 GIT_REPO_WITH_GROUP = '%s/%s' % (REPO_GROUP, GIT_REPO)
49 GIT_REPO_WITH_GROUP = '%s/%s' % (REPO_GROUP, GIT_REPO)
50
50
51
51
52 @pytest.fixture(scope="module")
52 @pytest.fixture(scope="module")
53 def rcextensions(request, db_connection, tmpdir_factory):
53 def rcextensions(request, db_connection, tmpdir_factory):
54 """
54 """
55 Installs a testing rcextensions pack to ensure they work as expected.
55 Installs a testing rcextensions pack to ensure they work as expected.
56 """
56 """
57 init_content = textwrap.dedent("""
57 init_content = textwrap.dedent("""
58 # Forward import the example rcextensions to make it
58 # Forward import the example rcextensions to make it
59 # active for our tests.
59 # active for our tests.
60 from rhodecode.tests.other.example_rcextensions import *
60 from rhodecode.tests.other.example_rcextensions import *
61 """)
61 """)
62
62
63 # Note: rcextensions are looked up based on the path of the ini file
63 # Note: rcextensions are looked up based on the path of the ini file
64 root_path = tmpdir_factory.getbasetemp()
64 root_path = tmpdir_factory.getbasetemp()
65 rcextensions_path = root_path.join('rcextensions')
65 rcextensions_path = root_path.join('rcextensions')
66 init_path = rcextensions_path.join('__init__.py')
66 init_path = rcextensions_path.join('__init__.py')
67
67
68 if rcextensions_path.check():
68 if rcextensions_path.check():
69 pytest.fail(
69 pytest.fail(
70 "Path for rcextensions already exists, please clean up before "
70 "Path for rcextensions already exists, please clean up before "
71 "test run this path: %s" % (rcextensions_path, ))
71 "test run this path: %s" % (rcextensions_path, ))
72 return
72 return
73
73
74 request.addfinalizer(rcextensions_path.remove)
74 request.addfinalizer(rcextensions_path.remove)
75 init_path.write_binary(init_content, ensure=True)
75 init_path.write_binary(init_content, ensure=True)
76
76
77
77
78 @pytest.fixture(scope="module")
78 @pytest.fixture(scope="module")
79 def repos(request, db_connection):
79 def repos(request, db_connection):
80 """Create a copy of each test repo in a repo group."""
80 """Create a copy of each test repo in a repo group."""
81 fixture = Fixture()
81 fixture = Fixture()
82 repo_group = fixture.create_repo_group(REPO_GROUP)
82 repo_group = fixture.create_repo_group(REPO_GROUP)
83 repo_group_id = repo_group.group_id
83 repo_group_id = repo_group.group_id
84 fixture.create_fork(HG_REPO, HG_REPO,
84 fixture.create_fork(HG_REPO, HG_REPO,
85 repo_name_full=HG_REPO_WITH_GROUP,
85 repo_name_full=HG_REPO_WITH_GROUP,
86 repo_group=repo_group_id)
86 repo_group=repo_group_id)
87 fixture.create_fork(GIT_REPO, GIT_REPO,
87 fixture.create_fork(GIT_REPO, GIT_REPO,
88 repo_name_full=GIT_REPO_WITH_GROUP,
88 repo_name_full=GIT_REPO_WITH_GROUP,
89 repo_group=repo_group_id)
89 repo_group=repo_group_id)
90
90
91 @request.addfinalizer
91 @request.addfinalizer
92 def cleanup():
92 def cleanup():
93 fixture.destroy_repo(HG_REPO_WITH_GROUP)
93 fixture.destroy_repo(HG_REPO_WITH_GROUP)
94 fixture.destroy_repo(GIT_REPO_WITH_GROUP)
94 fixture.destroy_repo(GIT_REPO_WITH_GROUP)
95 fixture.destroy_repo_group(repo_group_id)
95 fixture.destroy_repo_group(repo_group_id)
96
96
97
97
98 @pytest.fixture(scope="module")
98 @pytest.fixture(scope="module")
99 def rc_web_server_config_modification():
99 def rc_web_server_config_modification():
100 return []
100 return []
101
101
102
102
103 @pytest.fixture(scope="module")
103 @pytest.fixture(scope="module")
104 def rc_web_server_config_factory(testini_factory, rc_web_server_config_modification):
104 def rc_web_server_config_factory(testini_factory, rc_web_server_config_modification):
105 """
105 """
106 Configuration file used for the fixture `rc_web_server`.
106 Configuration file used for the fixture `rc_web_server`.
107 """
107 """
108
108
109 def factory(vcsserver_port):
109 def factory(rcweb_port, vcsserver_port):
110 custom_params = [
110 custom_params = [
111 {'handler_console': {'level': 'DEBUG'}},
111 {'handler_console': {'level': 'DEBUG'}},
112 {'server:main': {'port': rcweb_port}},
112 {'app:main': {'vcs.server': 'localhost:%s' % vcsserver_port}}
113 {'app:main': {'vcs.server': 'localhost:%s' % vcsserver_port}}
113 ]
114 ]
114 custom_params.extend(rc_web_server_config_modification)
115 custom_params.extend(rc_web_server_config_modification)
115 return testini_factory(custom_params)
116 return testini_factory(custom_params)
116 return factory
117 return factory
117
118
118
119
119 @pytest.fixture(scope="module")
120 @pytest.fixture(scope="module")
120 def rc_web_server(
121 def rc_web_server(
121 request, vcsserver_factory, available_port_factory,
122 request, vcsserver_factory, available_port_factory,
122 rc_web_server_config_factory, repos, rcextensions):
123 rc_web_server_config_factory, repos, rcextensions):
123 """
124 """
124 Run the web server as a subprocess. with it's own instance of vcsserver
125 Run the web server as a subprocess. with it's own instance of vcsserver
125 """
126 """
127 rcweb_port = available_port_factory()
128 print('Using rcweb ops test port {}'.format(rcweb_port))
126
129
127 vcsserver_port = available_port_factory()
130 vcsserver_port = available_port_factory()
128 print('Using vcsserver ops test port {}'.format(vcsserver_port))
131 print('Using vcsserver ops test port {}'.format(vcsserver_port))
129
132
130 vcs_log = os.path.join(tempfile.gettempdir(), 'rc_op_vcs.log')
133 vcs_log = os.path.join(tempfile.gettempdir(), 'rc_op_vcs.log')
131 vcsserver_factory(
134 vcsserver_factory(
132 request, vcsserver_port=vcsserver_port,
135 request, vcsserver_port=vcsserver_port,
133 log_file=vcs_log,
136 log_file=vcs_log,
134 overrides=(
137 overrides=(
135 {'server:main': {'workers': 2}},
138 {'server:main': {'workers': 2}},
136 {'server:main': {'graceful_timeout': 10}},
139 {'server:main': {'graceful_timeout': 10}},
137 ))
140 ))
138
141
139 rc_log = os.path.join(tempfile.gettempdir(), 'rc_op_web.log')
142 rc_log = os.path.join(tempfile.gettempdir(), 'rc_op_web.log')
140 rc_web_server_config = rc_web_server_config_factory(
143 rc_web_server_config = rc_web_server_config_factory(
144 rcweb_port=rcweb_port,
141 vcsserver_port=vcsserver_port)
145 vcsserver_port=vcsserver_port)
142 server = RcWebServer(rc_web_server_config, log_file=rc_log)
146 server = RcWebServer(rc_web_server_config, log_file=rc_log)
143 server.start()
147 server.start()
144
148
145 @request.addfinalizer
149 @request.addfinalizer
146 def cleanup():
150 def cleanup():
147 server.shutdown()
151 server.shutdown()
148
152
149 server.wait_until_ready()
153 server.wait_until_ready()
150 return server
154 return server
151
155
152
156
153 @pytest.fixture
157 @pytest.fixture
154 def disable_locking(baseapp):
158 def disable_locking(baseapp):
155 r = Repository.get_by_repo_name(GIT_REPO)
159 r = Repository.get_by_repo_name(GIT_REPO)
156 Repository.unlock(r)
160 Repository.unlock(r)
157 r.enable_locking = False
161 r.enable_locking = False
158 Session().add(r)
162 Session().add(r)
159 Session().commit()
163 Session().commit()
160
164
161 r = Repository.get_by_repo_name(HG_REPO)
165 r = Repository.get_by_repo_name(HG_REPO)
162 Repository.unlock(r)
166 Repository.unlock(r)
163 r.enable_locking = False
167 r.enable_locking = False
164 Session().add(r)
168 Session().add(r)
165 Session().commit()
169 Session().commit()
166
170
167
171
168 @pytest.fixture
172 @pytest.fixture
169 def enable_auth_plugins(request, baseapp, csrf_token):
173 def enable_auth_plugins(request, baseapp, csrf_token):
170 """
174 """
171 Return a factory object that when called, allows to control which
175 Return a factory object that when called, allows to control which
172 authentication plugins are enabled.
176 authentication plugins are enabled.
173 """
177 """
174 def _enable_plugins(plugins_list, override=None):
178 def _enable_plugins(plugins_list, override=None):
175 override = override or {}
179 override = override or {}
176 params = {
180 params = {
177 'auth_plugins': ','.join(plugins_list),
181 'auth_plugins': ','.join(plugins_list),
178 }
182 }
179
183
180 # helper translate some names to others
184 # helper translate some names to others
181 name_map = {
185 name_map = {
182 'token': 'authtoken'
186 'token': 'authtoken'
183 }
187 }
184
188
185 for module in plugins_list:
189 for module in plugins_list:
186 plugin_name = module.partition('#')[-1]
190 plugin_name = module.partition('#')[-1]
187 if plugin_name in name_map:
191 if plugin_name in name_map:
188 plugin_name = name_map[plugin_name]
192 plugin_name = name_map[plugin_name]
189 enabled_plugin = 'auth_%s_enabled' % plugin_name
193 enabled_plugin = 'auth_%s_enabled' % plugin_name
190 cache_ttl = 'auth_%s_cache_ttl' % plugin_name
194 cache_ttl = 'auth_%s_cache_ttl' % plugin_name
191
195
192 # default params that are needed for each plugin,
196 # default params that are needed for each plugin,
193 # `enabled` and `cache_ttl`
197 # `enabled` and `cache_ttl`
194 params.update({
198 params.update({
195 enabled_plugin: True,
199 enabled_plugin: True,
196 cache_ttl: 0
200 cache_ttl: 0
197 })
201 })
198 if override.get:
202 if override.get:
199 params.update(override.get(module, {}))
203 params.update(override.get(module, {}))
200
204
201 validated_params = params
205 validated_params = params
202 for k, v in validated_params.items():
206 for k, v in validated_params.items():
203 setting = SettingsModel().create_or_update_setting(k, v)
207 setting = SettingsModel().create_or_update_setting(k, v)
204 Session().add(setting)
208 Session().add(setting)
205 Session().commit()
209 Session().commit()
206
210
207 def cleanup():
211 def cleanup():
208 _enable_plugins(['egg:rhodecode-enterprise-ce#rhodecode'])
212 _enable_plugins(['egg:rhodecode-enterprise-ce#rhodecode'])
209
213
210 request.addfinalizer(cleanup)
214 request.addfinalizer(cleanup)
211
215
212 return _enable_plugins
216 return _enable_plugins
213
217
214
218
215 @pytest.fixture
219 @pytest.fixture
216 def fs_repo_only(request, rhodecode_fixtures):
220 def fs_repo_only(request, rhodecode_fixtures):
217 def fs_repo_fabric(repo_name, repo_type):
221 def fs_repo_fabric(repo_name, repo_type):
218 rhodecode_fixtures.create_repo(repo_name, repo_type=repo_type)
222 rhodecode_fixtures.create_repo(repo_name, repo_type=repo_type)
219 rhodecode_fixtures.destroy_repo(repo_name, fs_remove=False)
223 rhodecode_fixtures.destroy_repo(repo_name, fs_remove=False)
220
224
221 def cleanup():
225 def cleanup():
222 rhodecode_fixtures.destroy_repo(repo_name, fs_remove=True)
226 rhodecode_fixtures.destroy_repo(repo_name, fs_remove=True)
223 rhodecode_fixtures.destroy_repo_on_filesystem(repo_name)
227 rhodecode_fixtures.destroy_repo_on_filesystem(repo_name)
224
228
225 request.addfinalizer(cleanup)
229 request.addfinalizer(cleanup)
226
230
227 return fs_repo_fabric
231 return fs_repo_fabric
228
232
229
233
230 @pytest.fixture
234 @pytest.fixture
231 def enable_webhook_push_integration(request):
235 def enable_webhook_push_integration(request):
232 integration = Integration()
236 integration = Integration()
233 integration.integration_type = WebhookIntegrationType.key
237 integration.integration_type = WebhookIntegrationType.key
234 Session().add(integration)
238 Session().add(integration)
235
239
236 settings = dict(
240 settings = dict(
237 url='http://httpbin.org',
241 url='http://httpbin.org',
238 secret_token='secret',
242 secret_token='secret',
239 username=None,
243 username=None,
240 password=None,
244 password=None,
241 custom_header_key=None,
245 custom_header_key=None,
242 custom_header_val=None,
246 custom_header_val=None,
243 method_type='get',
247 method_type='get',
244 events=[events.RepoPushEvent.name],
248 events=[events.RepoPushEvent.name],
245 log_data=True
249 log_data=True
246 )
250 )
247
251
248 IntegrationModel().update_integration(
252 IntegrationModel().update_integration(
249 integration,
253 integration,
250 name='IntegrationWebhookTest',
254 name='IntegrationWebhookTest',
251 enabled=True,
255 enabled=True,
252 settings=settings,
256 settings=settings,
253 repo=None,
257 repo=None,
254 repo_group=None,
258 repo_group=None,
255 child_repos_only=False,
259 child_repos_only=False,
256 )
260 )
257 Session().commit()
261 Session().commit()
258 integration_id = integration.integration_id
262 integration_id = integration.integration_id
259
263
260 @request.addfinalizer
264 @request.addfinalizer
261 def cleanup():
265 def cleanup():
262 integration = Integration.get(integration_id)
266 integration = Integration.get(integration_id)
263 Session().delete(integration)
267 Session().delete(integration)
264 Session().commit()
268 Session().commit()
265
269
General Comments 0
You need to be logged in to leave comments. Login now