userver: /data/code/userver/testsuite/pytest_plugins/pytest_userver/plugins/postgresql.py Source File
Loading...
Searching...
No Matches
postgresql.py
1"""
2Plugin that imports the required fixtures to start the database
3and adjusts the PostgreSQL "dbconnection" static config value.
4"""
5
6from contextlib import contextmanager
7from enum import Enum
8import typing
9
10import pytest
11
12from pytest_userver import sql
13
14pytest_plugins = [
15 'testsuite.databases.pgsql.pytest_plugin',
16 'pytest_userver.plugins.core',
17]
18
19
20USERVER_CONFIG_HOOKS = ['userver_pg_config']
21
22
24 Error = 1
25 LogicError = 2
26 RuntimeError = 3
27 ConnectionError = 4
28
29
31 def __init__(self, testpoint):
32 self._registered_ntrx = dict()
33 self._testpoint = testpoint
34
35 def _enable_failure(
36 self, name: str, failure_type: RegisteredNtrxFailureType,
37 ) -> None:
38 self._registered_ntrx[name] = failure_type
39
40 @self._testpoint(f'pg_ntrx_execute::{name}')
41 def _failure_tp(data):
42 return {
43 'inject_failure': self.is_failure_enabled(name),
44 'failure_type': self._get_failure_type(name).name,
45 }
46
47 def _disable_failure(self, name: str) -> None:
48 if self.is_failure_enabled(name):
49 del self._registered_ntrx[name]
50
51 def _get_failure_type(self, name: str) -> RegisteredNtrxFailureType:
52 return self._registered_ntrx[name]
53
54 def is_failure_enabled(self, name: str) -> bool:
55 return name in self._registered_ntrx
56
57 @contextmanager
58 def mock_failure(
59 self,
60 name: str,
61 failure_type: RegisteredNtrxFailureType = RegisteredNtrxFailureType.Error,
62 ):
63 self._enable_failure(name, failure_type)
64 try:
65 yield
66 finally:
67 self._disable_failure(name)
68
69
70@pytest.fixture(scope='session')
71def userver_pg_config(pgsql_local):
72 """
73 Returns a function that adjusts the static configuration file for
74 the testsuite.
75 Sets the `dbconnection` to the testsuite started PostgreSQL credentials
76 if there's only one `dbconnection` in static config.
77
78 @ingroup userver_testsuite_fixtures
79 """
80
81 if not pgsql_local:
82 raise ValueError(
83 'Override the "pgsql_local" fixture so that testsuite knowns how '
84 'to start the PostgreSQL database',
85 )
86
87 if len(pgsql_local) > 1:
88 raise ValueError(
89 f'Found more than one entry in "pgsql_local": '
90 f'{list(pgsql_local.keys())}. '
91 f'The "userver_pg_config" fixture supports '
92 f'only one entry in "pgsql_local" fixture. The '
93 f'"userver_pg_config" fixture should be overridden and '
94 f'the "dbconnection" for the components::Postgres '
95 f'components should be adjusted via the overridden fixture.',
96 )
97
98 uri = list(pgsql_local.values())[0].get_uri()
99
100 def _patch_config(config_yaml, config_vars):
101 components = config_yaml['components_manager']['components']
102 postgre_dbs = {
103 name: params
104 for name, params in components.items()
105 if params
106 and ('dbconnection' in params or 'dbconnection#env' in params)
107 }
108
109 if len(postgre_dbs) > 1:
110 raise ValueError(
111 f'Found more than one components with "dbconnection": '
112 f'{list(postgre_dbs.keys())}. '
113 f'The "userver_pg_config" fixture should be overridden and '
114 f'the "dbconnection" for the components::Postgres '
115 f'components should be adjusted via the overridden fixture.',
116 )
117
118 for config in postgre_dbs.values():
119 config['dbconnection'] = uri
120 config.pop('dbalias', None)
121
122 return _patch_config
123
124
125@pytest.fixture
127 testpoint,
128) -> typing.Generator[sql.RegisteredTrx, None, None]:
129 """
130 The fixture maintains transaction fault injection state using
131 RegisteredTrx class.
132
133 @see pytest_userver.sql.RegisteredTrx
134
135 @snippet postgresql/functional_tests/integration_tests/tests/test_trx_failure.py fault injection
136
137 @ingroup userver_testsuite_fixtures
138 """ # noqa: E501
139
140 registered = sql.RegisteredTrx()
141
142 @testpoint('pg_trx_commit')
143 def _pg_trx_tp(data):
144 should_fail = registered.is_failure_enabled(data['trx_name'])
145 return {'trx_should_fail': should_fail}
146
147 yield registered
148
149
150@pytest.fixture
151def userver_pg_ntrx(testpoint) -> typing.Generator[RegisteredNtrx, None, None]:
152 """
153 The fixture maintains single query fault injection state using
154 RegisteredNtrx class.
155
156 @see pytest_userver.plugins.postgresql.RegisteredNtrx
157
158 @snippet postgresql/functional_tests/integration_tests/tests/test_ntrx_failure.py fault injection
159
160 @ingroup userver_testsuite_fixtures
161 """ # noqa: E501
162
163 yield RegisteredNtrx(testpoint)