##// END OF EJS Templates
tests: use WARN loglevel by default, and add --test-loglevel flag to change this....
marcink -
r1123:c96fec20 default
parent child Browse files
Show More
@@ -1,455 +1,471 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 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 import json
21 import json
22 import logging.config
22 import logging.config
23 import os
23 import os
24 import platform
24 import platform
25 import socket
25 import socket
26 import subprocess32
26 import subprocess32
27 import time
27 import time
28 from urllib2 import urlopen, URLError
28 from urllib2 import urlopen, URLError
29
29
30 import configobj
30 import configobj
31 import pylons
31 import pylons
32 import pytest
32 import pytest
33 import webob
33 import webob
34 from beaker.session import SessionObject
34 from beaker.session import SessionObject
35 from paste.deploy import loadapp
35 from paste.deploy import loadapp
36 from pylons.i18n.translation import _get_translator
36 from pylons.i18n.translation import _get_translator
37 from pylons.util import ContextObj
37 from pylons.util import ContextObj
38 from Pyro4.errors import CommunicationError
38 from Pyro4.errors import CommunicationError
39 from routes.util import URLGenerator
39 from routes.util import URLGenerator
40
40
41 from rhodecode.lib import vcs
41 from rhodecode.lib import vcs
42 from rhodecode.tests.fixture import TestINI
42 from rhodecode.tests.fixture import TestINI
43 import rhodecode
43 import rhodecode
44
44
45
45
46 def _parse_json(value):
46 def _parse_json(value):
47 return json.loads(value) if value else None
47 return json.loads(value) if value else None
48
48
49
49
50 def pytest_addoption(parser):
50 def pytest_addoption(parser):
51 parser.addoption(
52 '--test-loglevel', dest='test_loglevel',
53 help="Set default Logging level for tests, warn (default), info, debug")
51 group = parser.getgroup('pylons')
54 group = parser.getgroup('pylons')
52 group.addoption(
55 group.addoption(
53 '--with-pylons', dest='pylons_config',
56 '--with-pylons', dest='pylons_config',
54 help="Set up a Pylons environment with the specified config file.")
57 help="Set up a Pylons environment with the specified config file.")
55 group.addoption(
58 group.addoption(
56 '--pylons-config-override', action='store', type=_parse_json,
59 '--pylons-config-override', action='store', type=_parse_json,
57 default=None, dest='pylons_config_override', help=(
60 default=None, dest='pylons_config_override', help=(
58 "Overrides the .ini file settings. Should be specified in JSON"
61 "Overrides the .ini file settings. Should be specified in JSON"
59 " format, e.g. '{\"section\": {\"parameter\": \"value\", ...}}'"
62 " format, e.g. '{\"section\": {\"parameter\": \"value\", ...}}'"
60 )
63 )
61 )
64 )
62 parser.addini(
65 parser.addini(
63 'pylons_config',
66 'pylons_config',
64 "Set up a Pylons environment with the specified config file.")
67 "Set up a Pylons environment with the specified config file.")
65
68
66 vcsgroup = parser.getgroup('vcs')
69 vcsgroup = parser.getgroup('vcs')
67 vcsgroup.addoption(
70 vcsgroup.addoption(
68 '--without-vcsserver', dest='with_vcsserver', action='store_false',
71 '--without-vcsserver', dest='with_vcsserver', action='store_false',
69 help="Do not start the VCSServer in a background process.")
72 help="Do not start the VCSServer in a background process.")
70 vcsgroup.addoption(
73 vcsgroup.addoption(
71 '--with-vcsserver', dest='vcsserver_config_pyro4',
74 '--with-vcsserver', dest='vcsserver_config_pyro4',
72 help="Start the VCSServer with the specified config file.")
75 help="Start the VCSServer with the specified config file.")
73 vcsgroup.addoption(
76 vcsgroup.addoption(
74 '--with-vcsserver-http', dest='vcsserver_config_http',
77 '--with-vcsserver-http', dest='vcsserver_config_http',
75 help="Start the HTTP VCSServer with the specified config file.")
78 help="Start the HTTP VCSServer with the specified config file.")
76 vcsgroup.addoption(
79 vcsgroup.addoption(
77 '--vcsserver-protocol', dest='vcsserver_protocol',
80 '--vcsserver-protocol', dest='vcsserver_protocol',
78 help="Start the VCSServer with HTTP / Pyro4 protocol support.")
81 help="Start the VCSServer with HTTP / Pyro4 protocol support.")
79 vcsgroup.addoption(
82 vcsgroup.addoption(
80 '--vcsserver-config-override', action='store', type=_parse_json,
83 '--vcsserver-config-override', action='store', type=_parse_json,
81 default=None, dest='vcsserver_config_override', help=(
84 default=None, dest='vcsserver_config_override', help=(
82 "Overrides the .ini file settings for the VCSServer. "
85 "Overrides the .ini file settings for the VCSServer. "
83 "Should be specified in JSON "
86 "Should be specified in JSON "
84 "format, e.g. '{\"section\": {\"parameter\": \"value\", ...}}'"
87 "format, e.g. '{\"section\": {\"parameter\": \"value\", ...}}'"
85 )
88 )
86 )
89 )
87 vcsgroup.addoption(
90 vcsgroup.addoption(
88 '--vcsserver-port', action='store', type=int,
91 '--vcsserver-port', action='store', type=int,
89 default=None, help=(
92 default=None, help=(
90 "Allows to set the port of the vcsserver. Useful when testing "
93 "Allows to set the port of the vcsserver. Useful when testing "
91 "against an already running server and random ports cause "
94 "against an already running server and random ports cause "
92 "trouble."))
95 "trouble."))
93 parser.addini(
96 parser.addini(
94 'vcsserver_config_pyro4',
97 'vcsserver_config_pyro4',
95 "Start the VCSServer with the specified config file.")
98 "Start the VCSServer with the specified config file.")
96 parser.addini(
99 parser.addini(
97 'vcsserver_config_http',
100 'vcsserver_config_http',
98 "Start the HTTP VCSServer with the specified config file.")
101 "Start the HTTP VCSServer with the specified config file.")
99 parser.addini(
102 parser.addini(
100 'vcsserver_protocol',
103 'vcsserver_protocol',
101 "Start the VCSServer with HTTP / Pyro4 protocol support.")
104 "Start the VCSServer with HTTP / Pyro4 protocol support.")
102
105
103
106
104 @pytest.fixture(scope='session')
107 @pytest.fixture(scope='session')
105 def vcsserver(request, vcsserver_port, vcsserver_factory):
108 def vcsserver(request, vcsserver_port, vcsserver_factory):
106 """
109 """
107 Session scope VCSServer.
110 Session scope VCSServer.
108
111
109 Tests wich need the VCSServer have to rely on this fixture in order
112 Tests wich need the VCSServer have to rely on this fixture in order
110 to ensure it will be running.
113 to ensure it will be running.
111
114
112 For specific needs, the fixture vcsserver_factory can be used. It allows to
115 For specific needs, the fixture vcsserver_factory can be used. It allows to
113 adjust the configuration file for the test run.
116 adjust the configuration file for the test run.
114
117
115 Command line args:
118 Command line args:
116
119
117 --without-vcsserver: Allows to switch this fixture off. You have to
120 --without-vcsserver: Allows to switch this fixture off. You have to
118 manually start the server.
121 manually start the server.
119
122
120 --vcsserver-port: Will expect the VCSServer to listen on this port.
123 --vcsserver-port: Will expect the VCSServer to listen on this port.
121 """
124 """
122
125
123 if not request.config.getoption('with_vcsserver'):
126 if not request.config.getoption('with_vcsserver'):
124 return None
127 return None
125
128
126 use_http = _use_vcs_http_server(request.config)
129 use_http = _use_vcs_http_server(request.config)
127 return vcsserver_factory(
130 return vcsserver_factory(
128 request, use_http=use_http, vcsserver_port=vcsserver_port)
131 request, use_http=use_http, vcsserver_port=vcsserver_port)
129
132
130
133
131 @pytest.fixture(scope='session')
134 @pytest.fixture(scope='session')
132 def vcsserver_factory(tmpdir_factory):
135 def vcsserver_factory(tmpdir_factory):
133 """
136 """
134 Use this if you need a running vcsserver with a special configuration.
137 Use this if you need a running vcsserver with a special configuration.
135 """
138 """
136
139
137 def factory(request, use_http=True, overrides=(), vcsserver_port=None):
140 def factory(request, use_http=True, overrides=(), vcsserver_port=None):
138
141
139 if vcsserver_port is None:
142 if vcsserver_port is None:
140 vcsserver_port = get_available_port()
143 vcsserver_port = get_available_port()
141
144
142 overrides = list(overrides)
145 overrides = list(overrides)
143 if use_http:
146 if use_http:
144 overrides.append({'server:main': {'port': vcsserver_port}})
147 overrides.append({'server:main': {'port': vcsserver_port}})
145 else:
148 else:
146 overrides.append({'DEFAULT': {'port': vcsserver_port}})
149 overrides.append({'DEFAULT': {'port': vcsserver_port}})
147
150
148 if is_cygwin():
151 if is_cygwin():
149 platform_override = {'DEFAULT': {
152 platform_override = {'DEFAULT': {
150 'beaker.cache.repo_object.type': 'nocache'}}
153 'beaker.cache.repo_object.type': 'nocache'}}
151 overrides.append(platform_override)
154 overrides.append(platform_override)
152
155
153 option_name = (
156 option_name = (
154 'vcsserver_config_http' if use_http else 'vcsserver_config_pyro4')
157 'vcsserver_config_http' if use_http else 'vcsserver_config_pyro4')
155 override_option_name = 'vcsserver_config_override'
158 override_option_name = 'vcsserver_config_override'
156 config_file = get_config(
159 config_file = get_config(
157 request.config, option_name=option_name,
160 request.config, option_name=option_name,
158 override_option_name=override_option_name, overrides=overrides,
161 override_option_name=override_option_name, overrides=overrides,
159 basetemp=tmpdir_factory.getbasetemp().strpath,
162 basetemp=tmpdir_factory.getbasetemp().strpath,
160 prefix='test_vcs_')
163 prefix='test_vcs_')
161
164
162 print "Using the VCSServer configuration", config_file
165 print "Using the VCSServer configuration", config_file
163 ServerClass = HttpVCSServer if use_http else Pyro4VCSServer
166 ServerClass = HttpVCSServer if use_http else Pyro4VCSServer
164 server = ServerClass(config_file)
167 server = ServerClass(config_file)
165 server.start()
168 server.start()
166
169
167 @request.addfinalizer
170 @request.addfinalizer
168 def cleanup():
171 def cleanup():
169 server.shutdown()
172 server.shutdown()
170
173
171 server.wait_until_ready()
174 server.wait_until_ready()
172 return server
175 return server
173
176
174 return factory
177 return factory
175
178
176
179
177 def is_cygwin():
180 def is_cygwin():
178 return 'cygwin' in platform.system().lower()
181 return 'cygwin' in platform.system().lower()
179
182
180
183
181 def _use_vcs_http_server(config):
184 def _use_vcs_http_server(config):
182 protocol_option = 'vcsserver_protocol'
185 protocol_option = 'vcsserver_protocol'
183 protocol = (
186 protocol = (
184 config.getoption(protocol_option) or
187 config.getoption(protocol_option) or
185 config.getini(protocol_option) or
188 config.getini(protocol_option) or
186 'http')
189 'http')
187 return protocol == 'http'
190 return protocol == 'http'
188
191
189
192
193 def _use_log_level(config):
194 level = config.getoption('test_loglevel') or 'warn'
195 return level.upper()
196
197
190 class VCSServer(object):
198 class VCSServer(object):
191 """
199 """
192 Represents a running VCSServer instance.
200 Represents a running VCSServer instance.
193 """
201 """
194
202
195 _args = []
203 _args = []
196
204
197 def start(self):
205 def start(self):
198 print("Starting the VCSServer: {}".format(self._args))
206 print("Starting the VCSServer: {}".format(self._args))
199 self.process = subprocess32.Popen(self._args)
207 self.process = subprocess32.Popen(self._args)
200
208
201 def wait_until_ready(self, timeout=30):
209 def wait_until_ready(self, timeout=30):
202 raise NotImplementedError()
210 raise NotImplementedError()
203
211
204 def shutdown(self):
212 def shutdown(self):
205 self.process.kill()
213 self.process.kill()
206
214
207
215
208 class Pyro4VCSServer(VCSServer):
216 class Pyro4VCSServer(VCSServer):
209 def __init__(self, config_file):
217 def __init__(self, config_file):
210 """
218 """
211 :param config_file: The config file to start the server with
219 :param config_file: The config file to start the server with
212 """
220 """
213
221
214 config_data = configobj.ConfigObj(config_file)
222 config_data = configobj.ConfigObj(config_file)
215 self._config = config_data['DEFAULT']
223 self._config = config_data['DEFAULT']
216
224
217 args = ['vcsserver', '--config', config_file]
225 args = ['vcsserver', '--config', config_file]
218 self._args = args
226 self._args = args
219
227
220 def wait_until_ready(self, timeout=30):
228 def wait_until_ready(self, timeout=30):
221 remote_server = vcs.create_vcsserver_proxy(
229 remote_server = vcs.create_vcsserver_proxy(
222 self.server_and_port, 'pyro4')
230 self.server_and_port, 'pyro4')
223 start = time.time()
231 start = time.time()
224 with remote_server:
232 with remote_server:
225 while time.time() - start < timeout:
233 while time.time() - start < timeout:
226 try:
234 try:
227 remote_server.ping()
235 remote_server.ping()
228 break
236 break
229 except CommunicationError:
237 except CommunicationError:
230 time.sleep(0.2)
238 time.sleep(0.2)
231 else:
239 else:
232 pytest.exit(
240 pytest.exit(
233 "Starting the VCSServer failed or took more than {} "
241 "Starting the VCSServer failed or took more than {} "
234 "seconds.".format(timeout))
242 "seconds.".format(timeout))
235
243
236 @property
244 @property
237 def server_and_port(self):
245 def server_and_port(self):
238 return '{host}:{port}'.format(**self._config)
246 return '{host}:{port}'.format(**self._config)
239
247
240
248
241 class HttpVCSServer(VCSServer):
249 class HttpVCSServer(VCSServer):
242 """
250 """
243 Represents a running VCSServer instance.
251 Represents a running VCSServer instance.
244 """
252 """
245 def __init__(self, config_file):
253 def __init__(self, config_file):
246 config_data = configobj.ConfigObj(config_file)
254 config_data = configobj.ConfigObj(config_file)
247 self._config = config_data['server:main']
255 self._config = config_data['server:main']
248
256
249 args = ['pserve', config_file]
257 args = ['pserve', config_file]
250 self._args = args
258 self._args = args
251
259
252 @property
260 @property
253 def http_url(self):
261 def http_url(self):
254 template = 'http://{host}:{port}/'
262 template = 'http://{host}:{port}/'
255 return template.format(**self._config)
263 return template.format(**self._config)
256
264
257 def start(self):
265 def start(self):
258 self.process = subprocess32.Popen(self._args)
266 self.process = subprocess32.Popen(self._args)
259
267
260 def wait_until_ready(self, timeout=30):
268 def wait_until_ready(self, timeout=30):
261 host = self._config['host']
269 host = self._config['host']
262 port = self._config['port']
270 port = self._config['port']
263 status_url = 'http://{host}:{port}/status'.format(host=host, port=port)
271 status_url = 'http://{host}:{port}/status'.format(host=host, port=port)
264 start = time.time()
272 start = time.time()
265
273
266 while time.time() - start < timeout:
274 while time.time() - start < timeout:
267 try:
275 try:
268 urlopen(status_url)
276 urlopen(status_url)
269 break
277 break
270 except URLError:
278 except URLError:
271 time.sleep(0.2)
279 time.sleep(0.2)
272 else:
280 else:
273 pytest.exit(
281 pytest.exit(
274 "Starting the VCSServer failed or took more than {} "
282 "Starting the VCSServer failed or took more than {} "
275 "seconds.".format(timeout))
283 "seconds.".format(timeout))
276
284
277 def shutdown(self):
285 def shutdown(self):
278 self.process.kill()
286 self.process.kill()
279
287
280
288
281 @pytest.fixture(scope='session')
289 @pytest.fixture(scope='session')
282 def pylons_config(request, tmpdir_factory, rcserver_port, vcsserver_port):
290 def pylons_config(request, tmpdir_factory, rcserver_port, vcsserver_port):
283 option_name = 'pylons_config'
291 option_name = 'pylons_config'
292 log_level = _use_log_level(request.config)
284
293
285 overrides = [
294 overrides = [
286 {'server:main': {'port': rcserver_port}},
295 {'server:main': {'port': rcserver_port}},
287 {'app:main': {
296 {'app:main': {
288 'vcs.server': 'localhost:%s' % vcsserver_port,
297 'vcs.server': 'localhost:%s' % vcsserver_port,
289 # johbo: We will always start the VCSServer on our own based on the
298 # johbo: We will always start the VCSServer on our own based on the
290 # fixtures of the test cases. For the test run it must always be
299 # fixtures of the test cases. For the test run it must always be
291 # off in the INI file.
300 # off in the INI file.
292 'vcs.start_server': 'false',
301 'vcs.start_server': 'false',
293 }},
302 }},
303
304 {'handler_console': {
305 'class ': 'StreamHandler',
306 'args ': '(sys.stderr,)',
307 'level': log_level,
308 }},
309
294 ]
310 ]
295 if _use_vcs_http_server(request.config):
311 if _use_vcs_http_server(request.config):
296 overrides.append({
312 overrides.append({
297 'app:main': {
313 'app:main': {
298 'vcs.server.protocol': 'http',
314 'vcs.server.protocol': 'http',
299 'vcs.scm_app_implementation': 'http',
315 'vcs.scm_app_implementation': 'http',
300 'vcs.hooks.protocol': 'http',
316 'vcs.hooks.protocol': 'http',
301 }
317 }
302 })
318 })
303 else:
319 else:
304 overrides.append({
320 overrides.append({
305 'app:main': {
321 'app:main': {
306 'vcs.server.protocol': 'pyro4',
322 'vcs.server.protocol': 'pyro4',
307 'vcs.scm_app_implementation': 'pyro4',
323 'vcs.scm_app_implementation': 'pyro4',
308 'vcs.hooks.protocol': 'pyro4',
324 'vcs.hooks.protocol': 'pyro4',
309 }
325 }
310 })
326 })
311
327
312 filename = get_config(
328 filename = get_config(
313 request.config, option_name=option_name,
329 request.config, option_name=option_name,
314 override_option_name='{}_override'.format(option_name),
330 override_option_name='{}_override'.format(option_name),
315 overrides=overrides,
331 overrides=overrides,
316 basetemp=tmpdir_factory.getbasetemp().strpath,
332 basetemp=tmpdir_factory.getbasetemp().strpath,
317 prefix='test_rce_')
333 prefix='test_rce_')
318 return filename
334 return filename
319
335
320
336
321 @pytest.fixture(scope='session')
337 @pytest.fixture(scope='session')
322 def rcserver_port(request):
338 def rcserver_port(request):
323 port = get_available_port()
339 port = get_available_port()
324 print 'Using rcserver port %s' % (port, )
340 print 'Using rcserver port %s' % (port, )
325 return port
341 return port
326
342
327
343
328 @pytest.fixture(scope='session')
344 @pytest.fixture(scope='session')
329 def vcsserver_port(request):
345 def vcsserver_port(request):
330 port = request.config.getoption('--vcsserver-port')
346 port = request.config.getoption('--vcsserver-port')
331 if port is None:
347 if port is None:
332 port = get_available_port()
348 port = get_available_port()
333 print 'Using vcsserver port %s' % (port, )
349 print 'Using vcsserver port %s' % (port, )
334 return port
350 return port
335
351
336
352
337 def get_available_port():
353 def get_available_port():
338 family = socket.AF_INET
354 family = socket.AF_INET
339 socktype = socket.SOCK_STREAM
355 socktype = socket.SOCK_STREAM
340 host = '127.0.0.1'
356 host = '127.0.0.1'
341
357
342 mysocket = socket.socket(family, socktype)
358 mysocket = socket.socket(family, socktype)
343 mysocket.bind((host, 0))
359 mysocket.bind((host, 0))
344 port = mysocket.getsockname()[1]
360 port = mysocket.getsockname()[1]
345 mysocket.close()
361 mysocket.close()
346 del mysocket
362 del mysocket
347 return port
363 return port
348
364
349
365
350 @pytest.fixture(scope='session')
366 @pytest.fixture(scope='session')
351 def available_port_factory():
367 def available_port_factory():
352 """
368 """
353 Returns a callable which returns free port numbers.
369 Returns a callable which returns free port numbers.
354 """
370 """
355 return get_available_port
371 return get_available_port
356
372
357
373
358 @pytest.fixture
374 @pytest.fixture
359 def available_port(available_port_factory):
375 def available_port(available_port_factory):
360 """
376 """
361 Gives you one free port for the current test.
377 Gives you one free port for the current test.
362
378
363 Uses "available_port_factory" to retrieve the port.
379 Uses "available_port_factory" to retrieve the port.
364 """
380 """
365 return available_port_factory()
381 return available_port_factory()
366
382
367
383
368 @pytest.fixture(scope='session')
384 @pytest.fixture(scope='session')
369 def pylonsapp(pylons_config, vcsserver, http_environ_session):
385 def pylonsapp(pylons_config, vcsserver, http_environ_session):
370 print "Using the RhodeCode configuration", pylons_config
386 print "Using the RhodeCode configuration", pylons_config
371 logging.config.fileConfig(
387 logging.config.fileConfig(
372 pylons_config, disable_existing_loggers=False)
388 pylons_config, disable_existing_loggers=False)
373 app = _setup_pylons_environment(pylons_config, http_environ_session)
389 app = _setup_pylons_environment(pylons_config, http_environ_session)
374 return app
390 return app
375
391
376
392
377 @pytest.fixture(scope='session')
393 @pytest.fixture(scope='session')
378 def testini_factory(tmpdir_factory, pylons_config):
394 def testini_factory(tmpdir_factory, pylons_config):
379 """
395 """
380 Factory to create an INI file based on TestINI.
396 Factory to create an INI file based on TestINI.
381
397
382 It will make sure to place the INI file in the correct directory.
398 It will make sure to place the INI file in the correct directory.
383 """
399 """
384 basetemp = tmpdir_factory.getbasetemp().strpath
400 basetemp = tmpdir_factory.getbasetemp().strpath
385 return TestIniFactory(basetemp, pylons_config)
401 return TestIniFactory(basetemp, pylons_config)
386
402
387
403
388 class TestIniFactory(object):
404 class TestIniFactory(object):
389
405
390 def __init__(self, basetemp, template_ini):
406 def __init__(self, basetemp, template_ini):
391 self._basetemp = basetemp
407 self._basetemp = basetemp
392 self._template_ini = template_ini
408 self._template_ini = template_ini
393
409
394 def __call__(self, ini_params, new_file_prefix='test'):
410 def __call__(self, ini_params, new_file_prefix='test'):
395 ini_file = TestINI(
411 ini_file = TestINI(
396 self._template_ini, ini_params=ini_params,
412 self._template_ini, ini_params=ini_params,
397 new_file_prefix=new_file_prefix, dir=self._basetemp)
413 new_file_prefix=new_file_prefix, dir=self._basetemp)
398 result = ini_file.create()
414 result = ini_file.create()
399 return result
415 return result
400
416
401
417
402 def get_config(
418 def get_config(
403 config, option_name, override_option_name, overrides=None,
419 config, option_name, override_option_name, overrides=None,
404 basetemp=None, prefix='test'):
420 basetemp=None, prefix='test'):
405 """
421 """
406 Find a configuration file and apply overrides for the given `prefix`.
422 Find a configuration file and apply overrides for the given `prefix`.
407 """
423 """
408 config_file = (
424 config_file = (
409 config.getoption(option_name) or config.getini(option_name))
425 config.getoption(option_name) or config.getini(option_name))
410 if not config_file:
426 if not config_file:
411 pytest.exit(
427 pytest.exit(
412 "Configuration error, could not extract {}.".format(option_name))
428 "Configuration error, could not extract {}.".format(option_name))
413
429
414 overrides = overrides or []
430 overrides = overrides or []
415 config_override = config.getoption(override_option_name)
431 config_override = config.getoption(override_option_name)
416 if config_override:
432 if config_override:
417 overrides.append(config_override)
433 overrides.append(config_override)
418 temp_ini_file = TestINI(
434 temp_ini_file = TestINI(
419 config_file, ini_params=overrides, new_file_prefix=prefix,
435 config_file, ini_params=overrides, new_file_prefix=prefix,
420 dir=basetemp)
436 dir=basetemp)
421
437
422 return temp_ini_file.create()
438 return temp_ini_file.create()
423
439
424
440
425 def _setup_pylons_environment(pylons_config, http_environ):
441 def _setup_pylons_environment(pylons_config, http_environ):
426 current_path = os.getcwd()
442 current_path = os.getcwd()
427 pylonsapp = loadapp(
443 pylonsapp = loadapp(
428 'config:' + pylons_config, relative_to=current_path)
444 'config:' + pylons_config, relative_to=current_path)
429
445
430 # Using rhodecode.CONFIG which is assigned during "load_environment".
446 # Using rhodecode.CONFIG which is assigned during "load_environment".
431 # The indirect approach is used, because "pylonsapp" may actually be
447 # The indirect approach is used, because "pylonsapp" may actually be
432 # the Pyramid application.
448 # the Pyramid application.
433 pylonsapp_config = rhodecode.CONFIG
449 pylonsapp_config = rhodecode.CONFIG
434 _init_stack(pylonsapp_config, environ=http_environ)
450 _init_stack(pylonsapp_config, environ=http_environ)
435
451
436 # For compatibility add the attribute "config" which would be
452 # For compatibility add the attribute "config" which would be
437 # present on the Pylons application.
453 # present on the Pylons application.
438 pylonsapp.config = pylonsapp_config
454 pylonsapp.config = pylonsapp_config
439 return pylonsapp
455 return pylonsapp
440
456
441
457
442 def _init_stack(config=None, environ=None):
458 def _init_stack(config=None, environ=None):
443 if not config:
459 if not config:
444 config = pylons.test.pylonsapp.config
460 config = pylons.test.pylonsapp.config
445 if not environ:
461 if not environ:
446 environ = {}
462 environ = {}
447 pylons.url._push_object(URLGenerator(config['routes.map'], environ or {}))
463 pylons.url._push_object(URLGenerator(config['routes.map'], environ or {}))
448 pylons.app_globals._push_object(config['pylons.app_globals'])
464 pylons.app_globals._push_object(config['pylons.app_globals'])
449 pylons.config._push_object(config)
465 pylons.config._push_object(config)
450 pylons.tmpl_context._push_object(ContextObj())
466 pylons.tmpl_context._push_object(ContextObj())
451 # Initialize a translator for tests that utilize i18n
467 # Initialize a translator for tests that utilize i18n
452 translator = _get_translator(pylons.config.get('lang'))
468 translator = _get_translator(pylons.config.get('lang'))
453 pylons.translator._push_object(translator)
469 pylons.translator._push_object(translator)
454 pylons.session._push_object(SessionObject(environ or {}))
470 pylons.session._push_object(SessionObject(environ or {}))
455 pylons.request._push_object(webob.Request.blank('', environ=environ))
471 pylons.request._push_object(webob.Request.blank('', environ=environ))
General Comments 0
You need to be logged in to leave comments. Login now