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