2Configure the service in testsuite.
8from typing
import Callable
9from typing
import Optional
13USERVER_CONFIG_HOOKS = [
'userver_base_prepare_service_config']
16def pytest_addoption(parser) -> None:
17 group = parser.getgroup(
'userver')
21 help=
'Path to service build directory.',
24 group = parser.getgroup(
'Test service')
28 help=
'Path to service binary.',
32 help=(
'Main HTTP port of the service (default: use the port from the static config)'),
38 help=(
'Monitor HTTP port of the service (default: use the port from the static config)'),
43 '--service-source-dir',
45 help=
'Path to service source directory.',
46 default=pathlib.Path(
'.'),
50def pytest_configure(config):
51 config.option.asyncio_mode =
'auto'
54@pytest.fixture(scope='session')
57 Returns the path to the service source directory that is set by command
58 line `--service-source-dir` option.
60 Override this fixture to change the way the path to the service
61 source directory is detected by testsuite.
63 @ingroup userver_testsuite_fixtures
65 return pytestconfig.option.service_source_dir
68@pytest.fixture(scope='session')
71 Returns the build directory set by command line `--build-dir` option.
73 Override this fixture to change the way the build directory is
74 detected by the testsuite.
76 @ingroup userver_testsuite_fixtures
78 return pytestconfig.option.build_dir
81@pytest.fixture(scope='session')
84 Returns the path to service binary set by command line `--service-binary`
87 Override this fixture to change the way the path to service binary is
88 detected by the testsuite.
90 @ingroup userver_testsuite_fixtures
92 return pytestconfig.option.service_binary
95@pytest.fixture(scope='session')
96def service_port(pytestconfig, _original_service_config, choose_free_port) -> int:
98 Returns the main listener port number of the service set by command line
99 `--service-port` option.
100 If no port is specified in the command line option, keeps the original port
101 specified in the static config.
103 Override this fixture to change the way the main listener port number is
104 detected by the testsuite.
106 @ingroup userver_testsuite_fixtures
108 return pytestconfig.option.service_port
or _get_port(
109 _original_service_config,
117@pytest.fixture(scope='session')
96def service_port(pytestconfig, _original_service_config, choose_free_port) -> int:
…
118def monitor_port(pytestconfig, _original_service_config, choose_free_port) -> int:
120 Returns the monitor listener port number of the service set by command line
121 `--monitor-port` option.
122 If no port is specified in the command line option, keeps the original port
123 specified in the static config.
125 Override this fixture to change the way the monitor listener port number
126 is detected by testsuite.
128 @ingroup userver_testsuite_fixtures
130 return pytestconfig.option.monitor_port
or _get_port(
131 _original_service_config,
118def monitor_port(pytestconfig, _original_service_config, choose_free_port) -> int:
…
140 original_service_config,
146 config_yaml = original_service_config.config_yaml
147 config_vars = original_service_config.config_vars
148 components = config_yaml[
'components_manager'][
'components']
149 listener = components.get(
'server', {}).get(listener_name, {})
152 port = listener.get(
'port',
None)
153 if isinstance(port, str)
and port.startswith(
'$'):
154 port = config_vars.get(port[1:],
None)
or listener.get(
160 f
'components_manager.components.server.{listener_name}.port '
161 f
'in the static config, or pass {option_name} pytest option, '
162 f
'or override the {port_fixture.__name__} fixture'
168_allocated_ports = set()
171@pytest.fixture(scope='session')
174 Returns a function that chooses a free port based on the hint given in the parameter.
176 @ingroup userver_testsuite_fixtures
178 return _choose_free_port
181def _choose_free_port(first_port_hint: Optional[int], /) -> int:
183 global _allocated_ports
184 if port
in _allocated_ports:
187 server.bind((
'0.0.0.0', port))
188 _allocated_ports.add(port)
190 except BaseException:
193 with socket.socket(socket.AF_INET, socket.SOCK_STREAM)
as server:
194 if first_port_hint
is not None:
195 for port
in range(first_port_hint, first_port_hint + 100):
196 if port := _try_port(port):
199 for _attempt
in random.sample(range(1024, 65535), k=100):
200 if port := _try_port(port):
203 raise RuntimeError(
'Failed to pick a free TCP port')
206@pytest.fixture(scope='session')
207def userver_base_prepare_service_config():
208 def patch_config(config, config_vars):
209 components = config[
'components_manager'][
'components']
210 if 'congestion-control' in components:
211 if components[
'congestion-control']
is None:
212 components[
'congestion-control'] = {}
214 components[
'congestion-control'][
'fake-mode'] =
True