##// END OF EJS Templates
tests(core): made the test flag setting more flexible....
super-admin -
r5338:151d5696 default
parent child Browse files
Show More
@@ -1,23 +1,27 b''
1 [pytest]
1 [pytest]
2 testpaths = rhodecode
2 testpaths = rhodecode
3 norecursedirs = rhodecode/public rhodecode/templates tests/scripts
3 norecursedirs = rhodecode/public rhodecode/templates tests/scripts
4 cache_dir = /tmp/.pytest_cache
4 cache_dir = /tmp/.pytest_cache
5
5
6 pyramid_config = rhodecode/tests/rhodecode.ini
6 pyramid_config = rhodecode/tests/rhodecode.ini
7 vcsserver_protocol = http
7 vcsserver_protocol = http
8 vcsserver_config_http = rhodecode/tests/vcsserver_http.ini
8 vcsserver_config_http = rhodecode/tests/vcsserver_http.ini
9
9
10 addopts =
10 addopts =
11 --pdbcls=IPython.terminal.debugger:TerminalPdb
11 --pdbcls=IPython.terminal.debugger:TerminalPdb
12 --strict-markers
12 --strict-markers
13 --capture=no
13 --capture=no
14 --show-capture=all
14 --show-capture=all
15
15
16 # --test-loglevel=INFO, show log-level during execution
16 # --test-loglevel=INFO, show log-level during execution
17
17
18 markers =
18 markers =
19 vcs_operations: Mark tests depending on a running RhodeCode instance.
19 vcs_operations: Mark tests depending on a running RhodeCode instance.
20 xfail_backends: Mark tests as xfail for given backends.
20 xfail_backends: Mark tests as xfail for given backends.
21 skip_backends: Mark tests as skipped for given backends.
21 skip_backends: Mark tests as skipped for given backends.
22 backends: Mark backends
22 backends: Mark backends
23 dbs: database markers for running tests for given DB
23 dbs: database markers for running tests for given DB
24
25 env =
26 RC_TEST=1
27 RUN_ENV=test
@@ -1,46 +1,52 b''
1 # test related requirements
1 # test related requirements
2
2
3 cov-core==1.15.0
3 cov-core==1.15.0
4 coverage==7.2.3
4 coverage==7.2.3
5 mock==5.0.2
5 mock==5.0.2
6 py==1.11.0
6 py==1.11.0
7 pytest-cov==4.0.0
7 pytest-cov==4.0.0
8 coverage==7.2.3
8 coverage==7.2.3
9 pytest==7.3.1
9 pytest==7.3.1
10 attrs==22.2.0
10 attrs==22.2.0
11 iniconfig==2.0.0
11 iniconfig==2.0.0
12 packaging==23.1
12 packaging==23.1
13 pluggy==1.0.0
13 pluggy==1.0.0
14 pytest-env==1.1.3
15 pytest==7.3.1
16 attrs==22.2.0
17 iniconfig==2.0.0
18 packaging==23.1
19 pluggy==1.0.0
14 pytest-rerunfailures==12.0
20 pytest-rerunfailures==12.0
15 pytest-profiling==1.7.0
21 pytest-profiling==1.7.0
16 gprof2dot==2022.7.29
22 gprof2dot==2022.7.29
17 pytest==7.3.1
23 pytest==7.3.1
18 attrs==22.2.0
24 attrs==22.2.0
19 iniconfig==2.0.0
25 iniconfig==2.0.0
20 packaging==23.1
26 packaging==23.1
21 pluggy==1.0.0
27 pluggy==1.0.0
22 six==1.16.0
28 six==1.16.0
23 pytest-runner==6.0.0
29 pytest-runner==6.0.0
24 pytest-sugar==0.9.7
30 pytest-sugar==0.9.7
25 packaging==23.1
31 packaging==23.1
26 pytest==7.3.1
32 pytest==7.3.1
27 attrs==22.2.0
33 attrs==22.2.0
28 iniconfig==2.0.0
34 iniconfig==2.0.0
29 packaging==23.1
35 packaging==23.1
30 pluggy==1.0.0
36 pluggy==1.0.0
31 termcolor==2.3.0
37 termcolor==2.3.0
32 pytest-timeout==2.1.0
38 pytest-timeout==2.1.0
33 pytest==7.3.1
39 pytest==7.3.1
34 attrs==22.2.0
40 attrs==22.2.0
35 iniconfig==2.0.0
41 iniconfig==2.0.0
36 packaging==23.1
42 packaging==23.1
37 pluggy==1.0.0
43 pluggy==1.0.0
38 webtest==3.0.0
44 webtest==3.0.0
39 beautifulsoup4==4.11.2
45 beautifulsoup4==4.11.2
40 soupsieve==2.4
46 soupsieve==2.4
41 waitress==3.0.0
47 waitress==3.0.0
42 webob==1.8.7
48 webob==1.8.7
43
49
44 # RhodeCode test-data
50 # RhodeCode test-data
45 rc_testdata @ https://code.rhodecode.com/upstream/rc-testdata-dist/raw/77378e9097f700b4c1b9391b56199fe63566b5c9/rc_testdata-0.11.0.tar.gz#egg=rc_testdata
51 rc_testdata @ https://code.rhodecode.com/upstream/rc-testdata-dist/raw/77378e9097f700b4c1b9391b56199fe63566b5c9/rc_testdata-0.11.0.tar.gz#egg=rc_testdata
46 rc_testdata==0.11.0
52 rc_testdata==0.11.0
@@ -1,91 +1,91 b''
1 # Copyright (C) 2010-2023 RhodeCode GmbH
1 # Copyright (C) 2010-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import os
19 import os
20 import datetime
20 import datetime
21 import collections
21 import collections
22 import logging
22 import logging
23
23
24
24
25 now = datetime.datetime.now()
25 now = datetime.datetime.now()
26 now = now.strftime("%Y-%m-%d %H:%M:%S") + '.' + f"{int(now.microsecond/1000):03d}"
26 now = now.strftime("%Y-%m-%d %H:%M:%S") + '.' + f"{int(now.microsecond/1000):03d}"
27
27
28 log = logging.getLogger(__name__)
28 log = logging.getLogger(__name__)
29 log.debug(f'{now} Starting RhodeCode imports...')
29 log.debug(f'{now} Starting RhodeCode imports...')
30
30
31
31
32 VERSION = tuple(open(os.path.join(
32 VERSION = tuple(open(os.path.join(
33 os.path.dirname(__file__), 'VERSION')).read().split('.'))
33 os.path.dirname(__file__), 'VERSION')).read().split('.'))
34
34
35 BACKENDS = collections.OrderedDict()
35 BACKENDS = collections.OrderedDict()
36
36
37 BACKENDS['hg'] = 'Mercurial repository'
37 BACKENDS['hg'] = 'Mercurial repository'
38 BACKENDS['git'] = 'Git repository'
38 BACKENDS['git'] = 'Git repository'
39 BACKENDS['svn'] = 'Subversion repository'
39 BACKENDS['svn'] = 'Subversion repository'
40
40
41
41
42 CELERY_ENABLED = False
42 CELERY_ENABLED = False
43 CELERY_EAGER = False
43 CELERY_EAGER = False
44
44
45 # link to config for pyramid
45 # link to config for pyramid
46 CONFIG = {}
46 CONFIG = {}
47
47
48
48
49 class ConfigGet:
49 class ConfigGet:
50 NotGiven = object()
50 NotGiven = object()
51
51
52 def _get_val_or_missing(self, key, missing):
52 def _get_val_or_missing(self, key, missing):
53 if key not in CONFIG:
53 if key not in CONFIG:
54 if missing == self.NotGiven:
54 if missing == self.NotGiven:
55 return missing
55 return missing
56 # we don't get key, we don't get missing value, return nothing similar as config.get(key)
56 # we don't get key, we don't get missing value, return nothing similar as config.get(key)
57 return None
57 return None
58 else:
58 else:
59 val = CONFIG[key]
59 val = CONFIG[key]
60 return val
60 return val
61
61
62 def get_str(self, key, missing=NotGiven):
62 def get_str(self, key, missing=NotGiven):
63 from rhodecode.lib.str_utils import safe_str
63 from rhodecode.lib.str_utils import safe_str
64 val = self._get_val_or_missing(key, missing)
64 val = self._get_val_or_missing(key, missing)
65 return safe_str(val)
65 return safe_str(val)
66
66
67 def get_int(self, key, missing=NotGiven):
67 def get_int(self, key, missing=NotGiven):
68 from rhodecode.lib.str_utils import safe_int
68 from rhodecode.lib.str_utils import safe_int
69 val = self._get_val_or_missing(key, missing)
69 val = self._get_val_or_missing(key, missing)
70 return safe_int(val)
70 return safe_int(val)
71
71
72 def get_bool(self, key, missing=NotGiven):
72 def get_bool(self, key, missing=NotGiven):
73 from rhodecode.lib.type_utils import str2bool
73 from rhodecode.lib.type_utils import str2bool
74 val = self._get_val_or_missing(key, missing)
74 val = self._get_val_or_missing(key, missing)
75 return str2bool(val)
75 return str2bool(val)
76
76
77 # Populated with the settings dictionary from application init in
77 # Populated with the settings dictionary from application init in
78 # rhodecode.conf.environment.load_pyramid_environment
78 # rhodecode.conf.environment.load_pyramid_environment
79 PYRAMID_SETTINGS = {}
79 PYRAMID_SETTINGS = {}
80
80
81 # Linked module for extensions
81 # Linked module for extensions
82 EXTENSIONS = {}
82 EXTENSIONS = {}
83
83
84 __version__ = ('.'.join((str(each) for each in VERSION[:3])))
84 __version__ = ('.'.join((str(each) for each in VERSION[:3])))
85 __dbversion__ = 114 # defines current db version for migrations
85 __dbversion__ = 114 # defines current db version for migrations
86 __license__ = 'AGPLv3, and Commercial License'
86 __license__ = 'AGPLv3, and Commercial License'
87 __author__ = 'RhodeCode GmbH'
87 __author__ = 'RhodeCode GmbH'
88 __url__ = 'https://code.rhodecode.com'
88 __url__ = 'https://code.rhodecode.com'
89
89
90 is_test = False
90 is_test = os.getenv('RC_TEST')
91 disable_error_handler = False
91 disable_error_handler = False
@@ -1,200 +1,199 b''
1 # Copyright (C) 2010-2023 RhodeCode GmbH
1 # Copyright (C) 2010-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import os
19 import os
20 import tempfile
20 import tempfile
21 import logging
21 import logging
22
22
23 from pyramid.settings import asbool
23 from pyramid.settings import asbool
24
24
25 from rhodecode.config.settings_maker import SettingsMaker
25 from rhodecode.config.settings_maker import SettingsMaker
26 from rhodecode.config import utils as config_utils
26 from rhodecode.config import utils as config_utils
27
27
28 log = logging.getLogger(__name__)
28 log = logging.getLogger(__name__)
29
29
30
30
31 def sanitize_settings_and_apply_defaults(global_config, settings):
31 def sanitize_settings_and_apply_defaults(global_config, settings):
32 """
32 """
33 Applies settings defaults and does all type conversion.
33 Applies settings defaults and does all type conversion.
34
34
35 We would move all settings parsing and preparation into this place, so that
35 We would move all settings parsing and preparation into this place, so that
36 we have only one place left which deals with this part. The remaining parts
36 we have only one place left which deals with this part. The remaining parts
37 of the application would start to rely fully on well-prepared settings.
37 of the application would start to rely fully on well-prepared settings.
38
38
39 This piece would later be split up per topic to avoid a big fat monster
39 This piece would later be split up per topic to avoid a big fat monster
40 function.
40 function.
41 """
41 """
42 jn = os.path.join
42 jn = os.path.join
43
43
44 global_settings_maker = SettingsMaker(global_config)
44 global_settings_maker = SettingsMaker(global_config)
45 global_settings_maker.make_setting('debug', default=False, parser='bool')
45 global_settings_maker.make_setting('debug', default=False, parser='bool')
46 debug_enabled = asbool(global_config.get('debug'))
46 debug_enabled = asbool(global_config.get('debug'))
47
47
48 settings_maker = SettingsMaker(settings)
48 settings_maker = SettingsMaker(settings)
49
49
50 settings_maker.make_setting(
50 settings_maker.make_setting(
51 'logging.autoconfigure',
51 'logging.autoconfigure',
52 default=False,
52 default=False,
53 parser='bool')
53 parser='bool')
54
54
55 logging_conf = jn(os.path.dirname(global_config.get('__file__')), 'logging.ini')
55 logging_conf = jn(os.path.dirname(global_config.get('__file__')), 'logging.ini')
56 settings_maker.enable_logging(logging_conf, level='INFO' if debug_enabled else 'DEBUG')
56 settings_maker.enable_logging(logging_conf, level='INFO' if debug_enabled else 'DEBUG')
57
57
58 # Default includes, possible to change as a user
58 # Default includes, possible to change as a user
59 pyramid_includes = settings_maker.make_setting('pyramid.includes', [], parser='list:newline')
59 pyramid_includes = settings_maker.make_setting('pyramid.includes', [], parser='list:newline')
60 log.debug(
60 log.debug(
61 "Using the following pyramid.includes: %s",
61 "Using the following pyramid.includes: %s",
62 pyramid_includes)
62 pyramid_includes)
63
63
64 settings_maker.make_setting('rhodecode.edition', 'Community Edition')
64 settings_maker.make_setting('rhodecode.edition', 'Community Edition')
65 settings_maker.make_setting('rhodecode.edition_id', 'CE')
65 settings_maker.make_setting('rhodecode.edition_id', 'CE')
66
66
67 if 'mako.default_filters' not in settings:
67 if 'mako.default_filters' not in settings:
68 # set custom default filters if we don't have it defined
68 # set custom default filters if we don't have it defined
69 settings['mako.imports'] = 'from rhodecode.lib.base import h_filter'
69 settings['mako.imports'] = 'from rhodecode.lib.base import h_filter'
70 settings['mako.default_filters'] = 'h_filter'
70 settings['mako.default_filters'] = 'h_filter'
71
71
72 if 'mako.directories' not in settings:
72 if 'mako.directories' not in settings:
73 mako_directories = settings.setdefault('mako.directories', [
73 mako_directories = settings.setdefault('mako.directories', [
74 # Base templates of the original application
74 # Base templates of the original application
75 'rhodecode:templates',
75 'rhodecode:templates',
76 ])
76 ])
77 log.debug(
77 log.debug(
78 "Using the following Mako template directories: %s",
78 "Using the following Mako template directories: %s",
79 mako_directories)
79 mako_directories)
80
80
81 # NOTE(marcink): fix redis requirement for schema of connection since 3.X
81 # NOTE(marcink): fix redis requirement for schema of connection since 3.X
82 if 'beaker.session.type' in settings and settings['beaker.session.type'] == 'ext:redis':
82 if 'beaker.session.type' in settings and settings['beaker.session.type'] == 'ext:redis':
83 raw_url = settings['beaker.session.url']
83 raw_url = settings['beaker.session.url']
84 if not raw_url.startswith(('redis://', 'rediss://', 'unix://')):
84 if not raw_url.startswith(('redis://', 'rediss://', 'unix://')):
85 settings['beaker.session.url'] = 'redis://' + raw_url
85 settings['beaker.session.url'] = 'redis://' + raw_url
86
86
87 settings_maker.make_setting('__file__', global_config.get('__file__'))
87 settings_maker.make_setting('__file__', global_config.get('__file__'))
88
88
89 # TODO: johbo: Re-think this, usually the call to config.include
89 # TODO: johbo: Re-think this, usually the call to config.include
90 # should allow to pass in a prefix.
90 # should allow to pass in a prefix.
91 settings_maker.make_setting('rhodecode.api.url', '/_admin/api')
91 settings_maker.make_setting('rhodecode.api.url', '/_admin/api')
92
92
93 # Sanitize generic settings.
93 # Sanitize generic settings.
94 settings_maker.make_setting('default_encoding', 'UTF-8', parser='list')
94 settings_maker.make_setting('default_encoding', 'UTF-8', parser='list')
95 settings_maker.make_setting('is_test', False, parser='bool')
96 settings_maker.make_setting('gzip_responses', False, parser='bool')
95 settings_maker.make_setting('gzip_responses', False, parser='bool')
97 settings_maker.make_setting('startup.import_repos', 'false', parser='bool')
96 settings_maker.make_setting('startup.import_repos', 'false', parser='bool')
98
97
99 # statsd
98 # statsd
100 settings_maker.make_setting('statsd.enabled', False, parser='bool')
99 settings_maker.make_setting('statsd.enabled', False, parser='bool')
101 settings_maker.make_setting('statsd.statsd_host', 'statsd-exporter', parser='string')
100 settings_maker.make_setting('statsd.statsd_host', 'statsd-exporter', parser='string')
102 settings_maker.make_setting('statsd.statsd_port', 9125, parser='int')
101 settings_maker.make_setting('statsd.statsd_port', 9125, parser='int')
103 settings_maker.make_setting('statsd.statsd_prefix', '')
102 settings_maker.make_setting('statsd.statsd_prefix', '')
104 settings_maker.make_setting('statsd.statsd_ipv6', False, parser='bool')
103 settings_maker.make_setting('statsd.statsd_ipv6', False, parser='bool')
105
104
106 settings_maker.make_setting('vcs.svn.compatible_version', '')
105 settings_maker.make_setting('vcs.svn.compatible_version', '')
107 settings_maker.make_setting('vcs.svn.proxy.enabled', True, parser='bool')
106 settings_maker.make_setting('vcs.svn.proxy.enabled', True, parser='bool')
108 settings_maker.make_setting('vcs.svn.proxy.host', 'http://svn:8090', parser='string')
107 settings_maker.make_setting('vcs.svn.proxy.host', 'http://svn:8090', parser='string')
109 settings_maker.make_setting('vcs.hooks.protocol', 'http')
108 settings_maker.make_setting('vcs.hooks.protocol', 'http')
110 settings_maker.make_setting('vcs.hooks.host', '*')
109 settings_maker.make_setting('vcs.hooks.host', '*')
111 settings_maker.make_setting('vcs.scm_app_implementation', 'http')
110 settings_maker.make_setting('vcs.scm_app_implementation', 'http')
112 settings_maker.make_setting('vcs.server', '')
111 settings_maker.make_setting('vcs.server', '')
113 settings_maker.make_setting('vcs.server.protocol', 'http')
112 settings_maker.make_setting('vcs.server.protocol', 'http')
114 settings_maker.make_setting('vcs.server.enable', 'true', parser='bool')
113 settings_maker.make_setting('vcs.server.enable', 'true', parser='bool')
115 settings_maker.make_setting('vcs.hooks.direct_calls', 'false', parser='bool')
114 settings_maker.make_setting('vcs.hooks.direct_calls', 'false', parser='bool')
116 settings_maker.make_setting('vcs.start_server', 'false', parser='bool')
115 settings_maker.make_setting('vcs.start_server', 'false', parser='bool')
117 settings_maker.make_setting('vcs.backends', 'hg, git, svn', parser='list')
116 settings_maker.make_setting('vcs.backends', 'hg, git, svn', parser='list')
118 settings_maker.make_setting('vcs.connection_timeout', 3600, parser='int')
117 settings_maker.make_setting('vcs.connection_timeout', 3600, parser='int')
119
118
120 settings_maker.make_setting('vcs.methods.cache', True, parser='bool')
119 settings_maker.make_setting('vcs.methods.cache', True, parser='bool')
121
120
122 # Support legacy values of vcs.scm_app_implementation. Legacy
121 # Support legacy values of vcs.scm_app_implementation. Legacy
123 # configurations may use 'rhodecode.lib.middleware.utils.scm_app_http', or
122 # configurations may use 'rhodecode.lib.middleware.utils.scm_app_http', or
124 # disabled since 4.13 'vcsserver.scm_app' which is now mapped to 'http'.
123 # disabled since 4.13 'vcsserver.scm_app' which is now mapped to 'http'.
125 scm_app_impl = settings['vcs.scm_app_implementation']
124 scm_app_impl = settings['vcs.scm_app_implementation']
126 if scm_app_impl in ['rhodecode.lib.middleware.utils.scm_app_http', 'vcsserver.scm_app']:
125 if scm_app_impl in ['rhodecode.lib.middleware.utils.scm_app_http', 'vcsserver.scm_app']:
127 settings['vcs.scm_app_implementation'] = 'http'
126 settings['vcs.scm_app_implementation'] = 'http'
128
127
129 settings_maker.make_setting('appenlight', False, parser='bool')
128 settings_maker.make_setting('appenlight', False, parser='bool')
130
129
131 temp_store = tempfile.gettempdir()
130 temp_store = tempfile.gettempdir()
132 tmp_cache_dir = jn(temp_store, 'rc_cache')
131 tmp_cache_dir = jn(temp_store, 'rc_cache')
133
132
134 # save default, cache dir, and use it for all backends later.
133 # save default, cache dir, and use it for all backends later.
135 default_cache_dir = settings_maker.make_setting(
134 default_cache_dir = settings_maker.make_setting(
136 'cache_dir',
135 'cache_dir',
137 default=tmp_cache_dir, default_when_empty=True,
136 default=tmp_cache_dir, default_when_empty=True,
138 parser='dir:ensured')
137 parser='dir:ensured')
139
138
140 # exception store cache
139 # exception store cache
141 settings_maker.make_setting(
140 settings_maker.make_setting(
142 'exception_tracker.store_path',
141 'exception_tracker.store_path',
143 default=jn(default_cache_dir, 'exc_store'), default_when_empty=True,
142 default=jn(default_cache_dir, 'exc_store'), default_when_empty=True,
144 parser='dir:ensured'
143 parser='dir:ensured'
145 )
144 )
146
145
147 settings_maker.make_setting(
146 settings_maker.make_setting(
148 'celerybeat-schedule.path',
147 'celerybeat-schedule.path',
149 default=jn(default_cache_dir, 'celerybeat_schedule', 'celerybeat-schedule.db'), default_when_empty=True,
148 default=jn(default_cache_dir, 'celerybeat_schedule', 'celerybeat-schedule.db'), default_when_empty=True,
150 parser='file:ensured'
149 parser='file:ensured'
151 )
150 )
152
151
153 settings_maker.make_setting('exception_tracker.send_email', False, parser='bool')
152 settings_maker.make_setting('exception_tracker.send_email', False, parser='bool')
154 settings_maker.make_setting('exception_tracker.email_prefix', '[RHODECODE ERROR]', default_when_empty=True)
153 settings_maker.make_setting('exception_tracker.email_prefix', '[RHODECODE ERROR]', default_when_empty=True)
155
154
156 # sessions, ensure file since no-value is memory
155 # sessions, ensure file since no-value is memory
157 settings_maker.make_setting('beaker.session.type', 'file')
156 settings_maker.make_setting('beaker.session.type', 'file')
158 settings_maker.make_setting('beaker.session.data_dir', jn(default_cache_dir, 'session_data'))
157 settings_maker.make_setting('beaker.session.data_dir', jn(default_cache_dir, 'session_data'))
159
158
160 # cache_general
159 # cache_general
161 settings_maker.make_setting('rc_cache.cache_general.backend', 'dogpile.cache.rc.file_namespace')
160 settings_maker.make_setting('rc_cache.cache_general.backend', 'dogpile.cache.rc.file_namespace')
162 settings_maker.make_setting('rc_cache.cache_general.expiration_time', 60 * 60 * 12, parser='int')
161 settings_maker.make_setting('rc_cache.cache_general.expiration_time', 60 * 60 * 12, parser='int')
163 settings_maker.make_setting('rc_cache.cache_general.arguments.filename', jn(default_cache_dir, 'rhodecode_cache_general.db'))
162 settings_maker.make_setting('rc_cache.cache_general.arguments.filename', jn(default_cache_dir, 'rhodecode_cache_general.db'))
164
163
165 # cache_perms
164 # cache_perms
166 settings_maker.make_setting('rc_cache.cache_perms.backend', 'dogpile.cache.rc.file_namespace')
165 settings_maker.make_setting('rc_cache.cache_perms.backend', 'dogpile.cache.rc.file_namespace')
167 settings_maker.make_setting('rc_cache.cache_perms.expiration_time', 60 * 60, parser='int')
166 settings_maker.make_setting('rc_cache.cache_perms.expiration_time', 60 * 60, parser='int')
168 settings_maker.make_setting('rc_cache.cache_perms.arguments.filename', jn(default_cache_dir, 'rhodecode_cache_perms_db'))
167 settings_maker.make_setting('rc_cache.cache_perms.arguments.filename', jn(default_cache_dir, 'rhodecode_cache_perms_db'))
169
168
170 # cache_repo
169 # cache_repo
171 settings_maker.make_setting('rc_cache.cache_repo.backend', 'dogpile.cache.rc.file_namespace')
170 settings_maker.make_setting('rc_cache.cache_repo.backend', 'dogpile.cache.rc.file_namespace')
172 settings_maker.make_setting('rc_cache.cache_repo.expiration_time', 60 * 60 * 24 * 30, parser='int')
171 settings_maker.make_setting('rc_cache.cache_repo.expiration_time', 60 * 60 * 24 * 30, parser='int')
173 settings_maker.make_setting('rc_cache.cache_repo.arguments.filename', jn(default_cache_dir, 'rhodecode_cache_repo_db'))
172 settings_maker.make_setting('rc_cache.cache_repo.arguments.filename', jn(default_cache_dir, 'rhodecode_cache_repo_db'))
174
173
175 # cache_license
174 # cache_license
176 settings_maker.make_setting('rc_cache.cache_license.backend', 'dogpile.cache.rc.file_namespace')
175 settings_maker.make_setting('rc_cache.cache_license.backend', 'dogpile.cache.rc.file_namespace')
177 settings_maker.make_setting('rc_cache.cache_license.expiration_time', 60 * 5, parser='int')
176 settings_maker.make_setting('rc_cache.cache_license.expiration_time', 60 * 5, parser='int')
178 settings_maker.make_setting('rc_cache.cache_license.arguments.filename', jn(default_cache_dir, 'rhodecode_cache_license_db'))
177 settings_maker.make_setting('rc_cache.cache_license.arguments.filename', jn(default_cache_dir, 'rhodecode_cache_license_db'))
179
178
180 # cache_repo_longterm memory, 96H
179 # cache_repo_longterm memory, 96H
181 settings_maker.make_setting('rc_cache.cache_repo_longterm.backend', 'dogpile.cache.rc.memory_lru')
180 settings_maker.make_setting('rc_cache.cache_repo_longterm.backend', 'dogpile.cache.rc.memory_lru')
182 settings_maker.make_setting('rc_cache.cache_repo_longterm.expiration_time', 345600, parser='int')
181 settings_maker.make_setting('rc_cache.cache_repo_longterm.expiration_time', 345600, parser='int')
183 settings_maker.make_setting('rc_cache.cache_repo_longterm.max_size', 10000, parser='int')
182 settings_maker.make_setting('rc_cache.cache_repo_longterm.max_size', 10000, parser='int')
184
183
185 # sql_cache_short
184 # sql_cache_short
186 settings_maker.make_setting('rc_cache.sql_cache_short.backend', 'dogpile.cache.rc.memory_lru')
185 settings_maker.make_setting('rc_cache.sql_cache_short.backend', 'dogpile.cache.rc.memory_lru')
187 settings_maker.make_setting('rc_cache.sql_cache_short.expiration_time', 30, parser='int')
186 settings_maker.make_setting('rc_cache.sql_cache_short.expiration_time', 30, parser='int')
188 settings_maker.make_setting('rc_cache.sql_cache_short.max_size', 10000, parser='int')
187 settings_maker.make_setting('rc_cache.sql_cache_short.max_size', 10000, parser='int')
189
188
190 # archive_cache
189 # archive_cache
191 settings_maker.make_setting('archive_cache.store_dir', jn(default_cache_dir, 'archive_cache'), default_when_empty=True,)
190 settings_maker.make_setting('archive_cache.store_dir', jn(default_cache_dir, 'archive_cache'), default_when_empty=True,)
192 settings_maker.make_setting('archive_cache.cache_size_gb', 10, parser='float')
191 settings_maker.make_setting('archive_cache.cache_size_gb', 10, parser='float')
193 settings_maker.make_setting('archive_cache.cache_shards', 10, parser='int')
192 settings_maker.make_setting('archive_cache.cache_shards', 10, parser='int')
194
193
195 settings_maker.env_expand()
194 settings_maker.env_expand()
196
195
197 # configure instance id
196 # configure instance id
198 config_utils.set_instance_id(settings)
197 config_utils.set_instance_id(settings)
199
198
200 return settings
199 return settings
@@ -1,89 +1,88 b''
1 # Copyright (C) 2010-2023 RhodeCode GmbH
1 # Copyright (C) 2010-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import os
19 import os
20 import logging
20 import logging
21 import rhodecode
21 import rhodecode
22 import collections
22 import collections
23
23
24 from rhodecode.config import utils
24 from rhodecode.config import utils
25
25
26 from rhodecode.lib.utils import load_rcextensions
26 from rhodecode.lib.utils import load_rcextensions
27 from rhodecode.lib.utils2 import str2bool
27 from rhodecode.lib.utils2 import str2bool
28 from rhodecode.lib.vcs import connect_vcs
28 from rhodecode.lib.vcs import connect_vcs
29
29
30 log = logging.getLogger(__name__)
30 log = logging.getLogger(__name__)
31
31
32
32
33 def load_pyramid_environment(global_config, settings):
33 def load_pyramid_environment(global_config, settings):
34 # Some parts of the code expect a merge of global and app settings.
34 # Some parts of the code expect a merge of global and app settings.
35 settings_merged = global_config.copy()
35 settings_merged = global_config.copy()
36 settings_merged.update(settings)
36 settings_merged.update(settings)
37
37
38 # TODO(marcink): probably not required anymore
38 # TODO(marcink): probably not required anymore
39 # configure channelstream,
39 # configure channelstream,
40 settings_merged['channelstream_config'] = {
40 settings_merged['channelstream_config'] = {
41 'enabled': str2bool(settings_merged.get('channelstream.enabled', False)),
41 'enabled': str2bool(settings_merged.get('channelstream.enabled', False)),
42 'server': settings_merged.get('channelstream.server'),
42 'server': settings_merged.get('channelstream.server'),
43 'secret': settings_merged.get('channelstream.secret')
43 'secret': settings_merged.get('channelstream.secret')
44 }
44 }
45
45
46 # If this is a test run we prepare the test environment like
46 # If this is a test run we prepare the test environment like
47 # creating a test database, test search index and test repositories.
47 # creating a test database, test search index and test repositories.
48 # This has to be done before the database connection is initialized.
48 # This has to be done before the database connection is initialized.
49 if settings['is_test']:
49 if rhodecode.is_test:
50 rhodecode.is_test = True
51 rhodecode.disable_error_handler = True
50 rhodecode.disable_error_handler = True
52 from rhodecode import authentication
51 from rhodecode import authentication
53 authentication.plugin_default_auth_ttl = 0
52 authentication.plugin_default_auth_ttl = 0
54
53
55 utils.initialize_test_environment(settings_merged)
54 utils.initialize_test_environment(settings_merged)
56
55
57 # Initialize the database connection.
56 # Initialize the database connection.
58 utils.initialize_database(settings_merged)
57 utils.initialize_database(settings_merged)
59
58
60 load_rcextensions(root_path=settings_merged['here'])
59 load_rcextensions(root_path=settings_merged['here'])
61
60
62 # Limit backends to `vcs.backends` from configuration, and preserve the order
61 # Limit backends to `vcs.backends` from configuration, and preserve the order
63 for alias in rhodecode.BACKENDS.keys():
62 for alias in rhodecode.BACKENDS.keys():
64 if alias not in settings['vcs.backends']:
63 if alias not in settings['vcs.backends']:
65 del rhodecode.BACKENDS[alias]
64 del rhodecode.BACKENDS[alias]
66
65
67 _sorted_backend = sorted(rhodecode.BACKENDS.items(),
66 _sorted_backend = sorted(rhodecode.BACKENDS.items(),
68 key=lambda item: settings['vcs.backends'].index(item[0]))
67 key=lambda item: settings['vcs.backends'].index(item[0]))
69 rhodecode.BACKENDS = collections.OrderedDict(_sorted_backend)
68 rhodecode.BACKENDS = collections.OrderedDict(_sorted_backend)
70
69
71 log.info('Enabled VCS backends: %s', rhodecode.BACKENDS.keys())
70 log.info('Enabled VCS backends: %s', rhodecode.BACKENDS.keys())
72
71
73 # initialize vcs client and optionally run the server if enabled
72 # initialize vcs client and optionally run the server if enabled
74 vcs_server_uri = settings['vcs.server']
73 vcs_server_uri = settings['vcs.server']
75 vcs_server_enabled = settings['vcs.server.enable']
74 vcs_server_enabled = settings['vcs.server.enable']
76
75
77 utils.configure_vcs(settings)
76 utils.configure_vcs(settings)
78
77
79 # Store the settings to make them available to other modules.
78 # Store the settings to make them available to other modules.
80
79
81 rhodecode.PYRAMID_SETTINGS = settings_merged
80 rhodecode.PYRAMID_SETTINGS = settings_merged
82 rhodecode.CONFIG = settings_merged
81 rhodecode.CONFIG = settings_merged
83 rhodecode.CONFIG['default_user_id'] = utils.get_default_user_id()
82 rhodecode.CONFIG['default_user_id'] = utils.get_default_user_id()
84 rhodecode.CONFIG['default_base_path'] = utils.get_default_base_path()
83 rhodecode.CONFIG['default_base_path'] = utils.get_default_base_path()
85
84
86 if vcs_server_enabled:
85 if vcs_server_enabled:
87 connect_vcs(vcs_server_uri, utils.get_vcs_server_protocol(settings))
86 connect_vcs(vcs_server_uri, utils.get_vcs_server_protocol(settings))
88 else:
87 else:
89 log.warning('vcs-server not enabled, vcs connection unavailable')
88 log.warning('vcs-server not enabled, vcs connection unavailable')
@@ -1,288 +1,287 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
19
20 from subprocess import Popen, PIPE
20 from subprocess import Popen, PIPE
21 import os
21 import os
22 import sys
22 import sys
23 import tempfile
23 import tempfile
24
24
25 import pytest
25 import pytest
26 from sqlalchemy.engine import url
26 from sqlalchemy.engine import url
27
27
28 from rhodecode.lib.str_utils import safe_str, safe_bytes
28 from rhodecode.lib.str_utils import safe_str, safe_bytes
29 from rhodecode.tests.fixture import TestINI
29 from rhodecode.tests.fixture import TestINI
30
30
31
31
32 def _get_dbs_from_metafunc(metafunc):
32 def _get_dbs_from_metafunc(metafunc):
33 dbs_mark = metafunc.definition.get_closest_marker('dbs')
33 dbs_mark = metafunc.definition.get_closest_marker('dbs')
34
34
35 if dbs_mark:
35 if dbs_mark:
36 # Supported backends by this test function, created from pytest.mark.dbs
36 # Supported backends by this test function, created from pytest.mark.dbs
37 backends = dbs_mark.args
37 backends = dbs_mark.args
38 else:
38 else:
39 backends = metafunc.config.getoption('--dbs')
39 backends = metafunc.config.getoption('--dbs')
40 return backends
40 return backends
41
41
42
42
43 def pytest_generate_tests(metafunc):
43 def pytest_generate_tests(metafunc):
44 # Support test generation based on --dbs parameter
44 # Support test generation based on --dbs parameter
45 if 'db_backend' in metafunc.fixturenames:
45 if 'db_backend' in metafunc.fixturenames:
46 requested_backends = set(metafunc.config.getoption('--dbs'))
46 requested_backends = set(metafunc.config.getoption('--dbs'))
47 backends = _get_dbs_from_metafunc(metafunc)
47 backends = _get_dbs_from_metafunc(metafunc)
48 backends = requested_backends.intersection(backends)
48 backends = requested_backends.intersection(backends)
49 # TODO: johbo: Disabling a backend did not work out with
49 # TODO: johbo: Disabling a backend did not work out with
50 # parametrization, find better way to achieve this.
50 # parametrization, find better way to achieve this.
51 if not backends:
51 if not backends:
52 metafunc.function._skip = True
52 metafunc.function._skip = True
53 metafunc.parametrize('db_backend_name', backends)
53 metafunc.parametrize('db_backend_name', backends)
54
54
55
55
56 def pytest_collection_modifyitems(session, config, items):
56 def pytest_collection_modifyitems(session, config, items):
57 remaining = [
57 remaining = [
58 i for i in items if not getattr(i.obj, '_skip', False)]
58 i for i in items if not getattr(i.obj, '_skip', False)]
59 items[:] = remaining
59 items[:] = remaining
60
60
61
61
62 @pytest.fixture()
62 @pytest.fixture()
63 def db_backend(
63 def db_backend(
64 request, db_backend_name, ini_config, tmpdir_factory):
64 request, db_backend_name, ini_config, tmpdir_factory):
65 basetemp = tmpdir_factory.getbasetemp().strpath
65 basetemp = tmpdir_factory.getbasetemp().strpath
66 klass = _get_backend(db_backend_name)
66 klass = _get_backend(db_backend_name)
67
67
68 option_name = '--{}-connection-string'.format(db_backend_name)
68 option_name = '--{}-connection-string'.format(db_backend_name)
69 connection_string = request.config.getoption(option_name) or None
69 connection_string = request.config.getoption(option_name) or None
70
70
71 return klass(
71 return klass(
72 config_file=ini_config, basetemp=basetemp,
72 config_file=ini_config, basetemp=basetemp,
73 connection_string=connection_string)
73 connection_string=connection_string)
74
74
75
75
76 def _get_backend(backend_type):
76 def _get_backend(backend_type):
77 return {
77 return {
78 'sqlite': SQLiteDBBackend,
78 'sqlite': SQLiteDBBackend,
79 'postgres': PostgresDBBackend,
79 'postgres': PostgresDBBackend,
80 'mysql': MySQLDBBackend,
80 'mysql': MySQLDBBackend,
81 '': EmptyDBBackend
81 '': EmptyDBBackend
82 }[backend_type]
82 }[backend_type]
83
83
84
84
85 class DBBackend(object):
85 class DBBackend(object):
86 _store = os.path.dirname(os.path.abspath(__file__))
86 _store = os.path.dirname(os.path.abspath(__file__))
87 _type = None
87 _type = None
88 _base_ini_config = [{'app:main': {'vcs.start_server': 'false',
88 _base_ini_config = [{'app:main': {'vcs.start_server': 'false',
89 'startup.import_repos': 'false',
89 'startup.import_repos': 'false'}}]
90 'is_test': 'False'}}]
91 _db_url = [{'app:main': {'sqlalchemy.db1.url': ''}}]
90 _db_url = [{'app:main': {'sqlalchemy.db1.url': ''}}]
92 _base_db_name = 'rhodecode_test_db_backend'
91 _base_db_name = 'rhodecode_test_db_backend'
93
92
94 def __init__(
93 def __init__(
95 self, config_file, db_name=None, basetemp=None,
94 self, config_file, db_name=None, basetemp=None,
96 connection_string=None):
95 connection_string=None):
97
96
98 from rhodecode.lib.vcs.backends.hg import largefiles_store
97 from rhodecode.lib.vcs.backends.hg import largefiles_store
99 from rhodecode.lib.vcs.backends.git import lfs_store
98 from rhodecode.lib.vcs.backends.git import lfs_store
100
99
101 self.fixture_store = os.path.join(self._store, self._type)
100 self.fixture_store = os.path.join(self._store, self._type)
102 self.db_name = db_name or self._base_db_name
101 self.db_name = db_name or self._base_db_name
103 self._base_ini_file = config_file
102 self._base_ini_file = config_file
104 self.stderr = ''
103 self.stderr = ''
105 self.stdout = ''
104 self.stdout = ''
106 self._basetemp = basetemp or tempfile.gettempdir()
105 self._basetemp = basetemp or tempfile.gettempdir()
107 self._repos_location = os.path.join(self._basetemp, 'rc_test_repos')
106 self._repos_location = os.path.join(self._basetemp, 'rc_test_repos')
108 self._repos_hg_largefiles_store = largefiles_store(self._basetemp)
107 self._repos_hg_largefiles_store = largefiles_store(self._basetemp)
109 self._repos_git_lfs_store = lfs_store(self._basetemp)
108 self._repos_git_lfs_store = lfs_store(self._basetemp)
110 self.connection_string = connection_string
109 self.connection_string = connection_string
111
110
112 @property
111 @property
113 def connection_string(self):
112 def connection_string(self):
114 return self._connection_string
113 return self._connection_string
115
114
116 @connection_string.setter
115 @connection_string.setter
117 def connection_string(self, new_connection_string):
116 def connection_string(self, new_connection_string):
118 if not new_connection_string:
117 if not new_connection_string:
119 new_connection_string = self.get_default_connection_string()
118 new_connection_string = self.get_default_connection_string()
120 else:
119 else:
121 new_connection_string = new_connection_string.format(
120 new_connection_string = new_connection_string.format(
122 db_name=self.db_name)
121 db_name=self.db_name)
123 url_parts = url.make_url(new_connection_string)
122 url_parts = url.make_url(new_connection_string)
124 self._connection_string = new_connection_string
123 self._connection_string = new_connection_string
125 self.user = url_parts.username
124 self.user = url_parts.username
126 self.password = url_parts.password
125 self.password = url_parts.password
127 self.host = url_parts.host
126 self.host = url_parts.host
128
127
129 def get_default_connection_string(self):
128 def get_default_connection_string(self):
130 raise NotImplementedError('default connection_string is required.')
129 raise NotImplementedError('default connection_string is required.')
131
130
132 def execute(self, cmd, env=None, *args):
131 def execute(self, cmd, env=None, *args):
133 """
132 """
134 Runs command on the system with given ``args``.
133 Runs command on the system with given ``args``.
135 """
134 """
136
135
137 command = cmd + ' ' + ' '.join(args)
136 command = cmd + ' ' + ' '.join(args)
138 sys.stdout.write(command)
137 sys.stdout.write(command)
139
138
140 # Tell Python to use UTF-8 encoding out stdout
139 # Tell Python to use UTF-8 encoding out stdout
141 _env = os.environ.copy()
140 _env = os.environ.copy()
142 _env['PYTHONIOENCODING'] = 'UTF-8'
141 _env['PYTHONIOENCODING'] = 'UTF-8'
143 if env:
142 if env:
144 _env.update(env)
143 _env.update(env)
145 self.p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, env=_env)
144 self.p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, env=_env)
146 self.stdout, self.stderr = self.p.communicate()
145 self.stdout, self.stderr = self.p.communicate()
147 stdout_str = safe_str(self.stdout)
146 stdout_str = safe_str(self.stdout)
148 sys.stdout.write(f'COMMAND:{command}\n')
147 sys.stdout.write(f'COMMAND:{command}\n')
149 sys.stdout.write(stdout_str)
148 sys.stdout.write(stdout_str)
150 return self.stdout, self.stderr
149 return self.stdout, self.stderr
151
150
152 def assert_returncode_success(self):
151 def assert_returncode_success(self):
153 from rich import print as pprint
152 from rich import print as pprint
154 if not self.p.returncode == 0:
153 if not self.p.returncode == 0:
155 pprint(safe_str(self.stderr))
154 pprint(safe_str(self.stderr))
156 raise AssertionError(f'non 0 retcode:{self.p.returncode}')
155 raise AssertionError(f'non 0 retcode:{self.p.returncode}')
157
156
158 def assert_correct_output(self, stdout, version):
157 def assert_correct_output(self, stdout, version):
159 assert b'UPGRADE FOR STEP %b COMPLETED' % safe_bytes(version) in stdout
158 assert b'UPGRADE FOR STEP %b COMPLETED' % safe_bytes(version) in stdout
160
159
161 def setup_rhodecode_db(self, ini_params=None, env=None):
160 def setup_rhodecode_db(self, ini_params=None, env=None):
162 if not ini_params:
161 if not ini_params:
163 ini_params = self._base_ini_config
162 ini_params = self._base_ini_config
164
163
165 ini_params.extend(self._db_url)
164 ini_params.extend(self._db_url)
166 with TestINI(self._base_ini_file, ini_params,
165 with TestINI(self._base_ini_file, ini_params,
167 self._type, destroy=True) as _ini_file:
166 self._type, destroy=True) as _ini_file:
168
167
169 if not os.path.isdir(self._repos_location):
168 if not os.path.isdir(self._repos_location):
170 os.makedirs(self._repos_location)
169 os.makedirs(self._repos_location)
171 if not os.path.isdir(self._repos_hg_largefiles_store):
170 if not os.path.isdir(self._repos_hg_largefiles_store):
172 os.makedirs(self._repos_hg_largefiles_store)
171 os.makedirs(self._repos_hg_largefiles_store)
173 if not os.path.isdir(self._repos_git_lfs_store):
172 if not os.path.isdir(self._repos_git_lfs_store):
174 os.makedirs(self._repos_git_lfs_store)
173 os.makedirs(self._repos_git_lfs_store)
175
174
176 return self.execute(
175 return self.execute(
177 "rc-setup-app {0} --user=marcink "
176 "rc-setup-app {0} --user=marcink "
178 "--email=marcin@rhodeocode.com --password={1} "
177 "--email=marcin@rhodeocode.com --password={1} "
179 "--repos={2} --force-yes".format(
178 "--repos={2} --force-yes".format(
180 _ini_file, 'qweqwe', self._repos_location), env=env)
179 _ini_file, 'qweqwe', self._repos_location), env=env)
181
180
182 def upgrade_database(self, ini_params=None):
181 def upgrade_database(self, ini_params=None):
183 if not ini_params:
182 if not ini_params:
184 ini_params = self._base_ini_config
183 ini_params = self._base_ini_config
185 ini_params.extend(self._db_url)
184 ini_params.extend(self._db_url)
186
185
187 test_ini = TestINI(
186 test_ini = TestINI(
188 self._base_ini_file, ini_params, self._type, destroy=True)
187 self._base_ini_file, ini_params, self._type, destroy=True)
189 with test_ini as ini_file:
188 with test_ini as ini_file:
190 if not os.path.isdir(self._repos_location):
189 if not os.path.isdir(self._repos_location):
191 os.makedirs(self._repos_location)
190 os.makedirs(self._repos_location)
192
191
193 return self.execute(
192 return self.execute(
194 "rc-upgrade-db {0} --force-yes".format(ini_file))
193 "rc-upgrade-db {0} --force-yes".format(ini_file))
195
194
196 def setup_db(self):
195 def setup_db(self):
197 raise NotImplementedError
196 raise NotImplementedError
198
197
199 def teardown_db(self):
198 def teardown_db(self):
200 raise NotImplementedError
199 raise NotImplementedError
201
200
202 def import_dump(self, dumpname):
201 def import_dump(self, dumpname):
203 raise NotImplementedError
202 raise NotImplementedError
204
203
205
204
206 class EmptyDBBackend(DBBackend):
205 class EmptyDBBackend(DBBackend):
207 _type = ''
206 _type = ''
208
207
209 def setup_db(self):
208 def setup_db(self):
210 pass
209 pass
211
210
212 def teardown_db(self):
211 def teardown_db(self):
213 pass
212 pass
214
213
215 def import_dump(self, dumpname):
214 def import_dump(self, dumpname):
216 pass
215 pass
217
216
218 def assert_returncode_success(self):
217 def assert_returncode_success(self):
219 assert True
218 assert True
220
219
221
220
222 class SQLiteDBBackend(DBBackend):
221 class SQLiteDBBackend(DBBackend):
223 _type = 'sqlite'
222 _type = 'sqlite'
224
223
225 def get_default_connection_string(self):
224 def get_default_connection_string(self):
226 return 'sqlite:///{}/{}.sqlite'.format(self._basetemp, self.db_name)
225 return 'sqlite:///{}/{}.sqlite'.format(self._basetemp, self.db_name)
227
226
228 def setup_db(self):
227 def setup_db(self):
229 # dump schema for tests
228 # dump schema for tests
230 # cp -v $TEST_DB_NAME
229 # cp -v $TEST_DB_NAME
231 self._db_url = [{'app:main': {
230 self._db_url = [{'app:main': {
232 'sqlalchemy.db1.url': self.connection_string}}]
231 'sqlalchemy.db1.url': self.connection_string}}]
233
232
234 def import_dump(self, dumpname):
233 def import_dump(self, dumpname):
235 dump = os.path.join(self.fixture_store, dumpname)
234 dump = os.path.join(self.fixture_store, dumpname)
236 target = os.path.join(self._basetemp, '{0.db_name}.sqlite'.format(self))
235 target = os.path.join(self._basetemp, '{0.db_name}.sqlite'.format(self))
237 return self.execute(f'cp -v {dump} {target}')
236 return self.execute(f'cp -v {dump} {target}')
238
237
239 def teardown_db(self):
238 def teardown_db(self):
240 target_db = os.path.join(self._basetemp, self.db_name)
239 target_db = os.path.join(self._basetemp, self.db_name)
241 return self.execute(f"rm -rf {target_db}.sqlite")
240 return self.execute(f"rm -rf {target_db}.sqlite")
242
241
243
242
244 class MySQLDBBackend(DBBackend):
243 class MySQLDBBackend(DBBackend):
245 _type = 'mysql'
244 _type = 'mysql'
246
245
247 def get_default_connection_string(self):
246 def get_default_connection_string(self):
248 return 'mysql://root:qweqwe@127.0.0.1/{}'.format(self.db_name)
247 return 'mysql://root:qweqwe@127.0.0.1/{}'.format(self.db_name)
249
248
250 def setup_db(self):
249 def setup_db(self):
251 # dump schema for tests
250 # dump schema for tests
252 # mysqldump -uroot -pqweqwe $TEST_DB_NAME
251 # mysqldump -uroot -pqweqwe $TEST_DB_NAME
253 self._db_url = [{'app:main': {
252 self._db_url = [{'app:main': {
254 'sqlalchemy.db1.url': self.connection_string}}]
253 'sqlalchemy.db1.url': self.connection_string}}]
255 return self.execute("mysql -v -u{} -p{} -e 'create database '{}';'".format(
254 return self.execute("mysql -v -u{} -p{} -e 'create database '{}';'".format(
256 self.user, self.password, self.db_name))
255 self.user, self.password, self.db_name))
257
256
258 def import_dump(self, dumpname):
257 def import_dump(self, dumpname):
259 dump = os.path.join(self.fixture_store, dumpname)
258 dump = os.path.join(self.fixture_store, dumpname)
260 return self.execute("mysql -u{} -p{} {} < {}".format(
259 return self.execute("mysql -u{} -p{} {} < {}".format(
261 self.user, self.password, self.db_name, dump))
260 self.user, self.password, self.db_name, dump))
262
261
263 def teardown_db(self):
262 def teardown_db(self):
264 return self.execute("mysql -v -u{} -p{} -e 'drop database '{}';'".format(
263 return self.execute("mysql -v -u{} -p{} -e 'drop database '{}';'".format(
265 self.user, self.password, self.db_name))
264 self.user, self.password, self.db_name))
266
265
267
266
268 class PostgresDBBackend(DBBackend):
267 class PostgresDBBackend(DBBackend):
269 _type = 'postgres'
268 _type = 'postgres'
270
269
271 def get_default_connection_string(self):
270 def get_default_connection_string(self):
272 return 'postgresql://postgres:qweqwe@localhost/{}'.format(self.db_name)
271 return 'postgresql://postgres:qweqwe@localhost/{}'.format(self.db_name)
273
272
274 def setup_db(self):
273 def setup_db(self):
275 # dump schema for tests
274 # dump schema for tests
276 # pg_dump -U postgres -h localhost $TEST_DB_NAME
275 # pg_dump -U postgres -h localhost $TEST_DB_NAME
277 self._db_url = [{'app:main': {'sqlalchemy.db1.url': self.connection_string}}]
276 self._db_url = [{'app:main': {'sqlalchemy.db1.url': self.connection_string}}]
278 cmd = f"PGPASSWORD={self.password} psql -U {self.user} -h localhost -c 'create database '{self.db_name}';'"
277 cmd = f"PGPASSWORD={self.password} psql -U {self.user} -h localhost -c 'create database '{self.db_name}';'"
279 return self.execute(cmd)
278 return self.execute(cmd)
280
279
281 def teardown_db(self):
280 def teardown_db(self):
282 cmd = f"PGPASSWORD={self.password} psql -U {self.user} -h localhost -c 'drop database if exists '{self.db_name}';'"
281 cmd = f"PGPASSWORD={self.password} psql -U {self.user} -h localhost -c 'drop database if exists '{self.db_name}';'"
283 return self.execute(cmd)
282 return self.execute(cmd)
284
283
285 def import_dump(self, dumpname):
284 def import_dump(self, dumpname):
286 dump = os.path.join(self.fixture_store, dumpname)
285 dump = os.path.join(self.fixture_store, dumpname)
287 cmd = f"PGPASSWORD={self.password} psql -U {self.user} -h localhost -d {self.db_name} -1 -f {dump}"
286 cmd = f"PGPASSWORD={self.password} psql -U {self.user} -h localhost -d {self.db_name} -1 -f {dump}"
288 return self.execute(cmd)
287 return self.execute(cmd)
General Comments 0
You need to be logged in to leave comments. Login now