testgres 1.13.4__tar.gz → 1.13.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {testgres-1.13.4/testgres.egg-info → testgres-1.13.6}/PKG-INFO +2 -2
- {testgres-1.13.4 → testgres-1.13.6}/pyproject.toml +10 -2
- {testgres-1.13.4 → testgres-1.13.6}/src/backup.py +1 -1
- {testgres-1.13.4 → testgres-1.13.6}/src/cache.py +1 -1
- {testgres-1.13.4 → testgres-1.13.6}/src/exceptions.py +22 -22
- testgres-1.13.6/src/impl/internal_utils.py +20 -0
- testgres-1.13.6/src/impl/platforms/internal_platform_utils.py +62 -0
- testgres-1.13.6/src/impl/platforms/internal_platform_utils_factory.py +23 -0
- testgres-1.13.6/src/impl/platforms/linux/internal_platform_utils.py +120 -0
- testgres-1.13.6/src/impl/platforms/win32/internal_platform_utils.py +17 -0
- {testgres-1.13.4 → testgres-1.13.6}/src/impl/port_manager__generic.py +11 -11
- {testgres-1.13.4 → testgres-1.13.6}/src/impl/port_manager__this_host.py +3 -3
- {testgres-1.13.4 → testgres-1.13.6}/src/node.py +120 -118
- {testgres-1.13.4 → testgres-1.13.6}/src/node_app.py +27 -30
- {testgres-1.13.4 → testgres-1.13.6}/src/port_manager.py +1 -1
- {testgres-1.13.4 → testgres-1.13.6}/src/raise_error.py +4 -4
- {testgres-1.13.4 → testgres-1.13.6}/src/utils.py +168 -86
- {testgres-1.13.4 → testgres-1.13.6/testgres.egg-info}/PKG-INFO +2 -2
- {testgres-1.13.4 → testgres-1.13.6}/testgres.egg-info/SOURCES.txt +5 -0
- {testgres-1.13.4 → testgres-1.13.6}/testgres.egg-info/requires.txt +1 -1
- {testgres-1.13.4 → testgres-1.13.6}/tests/test_os_ops_common.py +87 -73
- {testgres-1.13.4 → testgres-1.13.6}/tests/test_os_ops_local.py +2 -2
- {testgres-1.13.4 → testgres-1.13.6}/tests/test_os_ops_remote.py +5 -4
- {testgres-1.13.4 → testgres-1.13.6}/tests/test_raise_error.py +5 -5
- {testgres-1.13.4 → testgres-1.13.6}/tests/test_testgres_common.py +246 -150
- {testgres-1.13.4 → testgres-1.13.6}/tests/test_testgres_local.py +16 -16
- {testgres-1.13.4 → testgres-1.13.6}/tests/test_testgres_remote.py +5 -4
- {testgres-1.13.4 → testgres-1.13.6}/LICENSE +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/README.md +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/setup.cfg +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/src/__init__.py +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/src/api.py +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/src/config.py +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/src/connection.py +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/src/consts.py +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/src/decorators.py +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/src/defaults.py +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/src/enums.py +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/src/logger.py +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/src/pubsub.py +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/src/standby.py +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/testgres.egg-info/dependency_links.txt +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/testgres.egg-info/top_level.txt +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/tests/test_config.py +0 -0
- {testgres-1.13.4 → testgres-1.13.6}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: testgres
|
|
3
|
-
Version: 1.13.
|
|
3
|
+
Version: 1.13.6
|
|
4
4
|
Summary: Testing utility for PostgreSQL and its extensions
|
|
5
5
|
Author-email: Postgres Professional <testgres@postgrespro.ru>
|
|
6
6
|
License: PostgreSQL
|
|
@@ -27,7 +27,7 @@ Requires-Dist: port-for>=0.4
|
|
|
27
27
|
Requires-Dist: six>=1.9.0
|
|
28
28
|
Requires-Dist: psutil
|
|
29
29
|
Requires-Dist: packaging
|
|
30
|
-
Requires-Dist: testgres.os_ops<3.0.0,>=2.0
|
|
30
|
+
Requires-Dist: testgres.os_ops<3.0.0,>=2.1.0
|
|
31
31
|
Dynamic: license-file
|
|
32
32
|
|
|
33
33
|
[](https://github.com/postgrespro/testgres/actions/workflows/package-verification.yml)
|
|
@@ -9,9 +9,17 @@ build-backend = "setuptools.build_meta"
|
|
|
9
9
|
extend-ignore = ["E501"]
|
|
10
10
|
exclude = [".git", "__pycache__", "env", "venv"]
|
|
11
11
|
|
|
12
|
+
# Pytest settings
|
|
13
|
+
[tool.pytest.ini_options]
|
|
14
|
+
|
|
15
|
+
testpaths = ["tests"]
|
|
16
|
+
log_file_level = "NOTSET"
|
|
17
|
+
log_file_format = "%(levelname)8s [%(asctime)s] %(message)s"
|
|
18
|
+
log_file_date_format = "%Y-%m-%d %H:%M:%S"
|
|
19
|
+
|
|
12
20
|
[project]
|
|
13
21
|
name = "testgres"
|
|
14
|
-
version = "1.13.
|
|
22
|
+
version = "1.13.6"
|
|
15
23
|
|
|
16
24
|
description = "Testing utility for PostgreSQL and its extensions"
|
|
17
25
|
readme = "README.md"
|
|
@@ -54,7 +62,7 @@ dependencies = [
|
|
|
54
62
|
"six>=1.9.0",
|
|
55
63
|
"psutil",
|
|
56
64
|
"packaging",
|
|
57
|
-
"testgres.os_ops>=2.0
|
|
65
|
+
"testgres.os_ops>=2.1.0,<3.0.0",
|
|
58
66
|
]
|
|
59
67
|
|
|
60
68
|
[project.urls]
|
|
@@ -160,7 +160,7 @@ class NodeBackup(object):
|
|
|
160
160
|
node = NodeClass(name=name, base_dir=base_dir, conn_params=self.original_node.os_ops.conn_params)
|
|
161
161
|
|
|
162
162
|
assert node is not None
|
|
163
|
-
assert type(node)
|
|
163
|
+
assert type(node) is self.original_node.__class__
|
|
164
164
|
|
|
165
165
|
with clean_on_error(node) as node:
|
|
166
166
|
# Set a new port
|
|
@@ -34,7 +34,7 @@ def cached_initdb(data_dir, logfile=None, params=None, os_ops: OsOperations = No
|
|
|
34
34
|
|
|
35
35
|
def make_utility_path(name):
|
|
36
36
|
assert name is not None
|
|
37
|
-
assert type(name)
|
|
37
|
+
assert type(name) is str
|
|
38
38
|
|
|
39
39
|
if bin_path:
|
|
40
40
|
return os_ops.build_path(bin_path, name)
|
|
@@ -15,14 +15,14 @@ class PortForException(TestgresException):
|
|
|
15
15
|
self,
|
|
16
16
|
message: typing.Optional[str] = None,
|
|
17
17
|
):
|
|
18
|
-
assert message is None or type(message)
|
|
18
|
+
assert message is None or type(message) is str
|
|
19
19
|
super().__init__(message)
|
|
20
20
|
self._message = message
|
|
21
21
|
return
|
|
22
22
|
|
|
23
23
|
@property
|
|
24
24
|
def message(self) -> str:
|
|
25
|
-
assert self._message is None or type(self._message)
|
|
25
|
+
assert self._message is None or type(self._message) is str
|
|
26
26
|
if self._message is None:
|
|
27
27
|
return ""
|
|
28
28
|
return self._message
|
|
@@ -53,8 +53,8 @@ class QueryException(TestgresException):
|
|
|
53
53
|
message: typing.Optional[str] = None,
|
|
54
54
|
query: typing.Optional[str] = None
|
|
55
55
|
):
|
|
56
|
-
assert message is None or type(message)
|
|
57
|
-
assert query is None or type(query)
|
|
56
|
+
assert message is None or type(message) is str
|
|
57
|
+
assert query is None or type(query) is str
|
|
58
58
|
|
|
59
59
|
super().__init__(message)
|
|
60
60
|
|
|
@@ -64,8 +64,8 @@ class QueryException(TestgresException):
|
|
|
64
64
|
|
|
65
65
|
@property
|
|
66
66
|
def message(self) -> str:
|
|
67
|
-
assert self._description is None or type(self._description)
|
|
68
|
-
assert self._query is None or type(self._query)
|
|
67
|
+
assert self._description is None or type(self._description) is str
|
|
68
|
+
assert self._query is None or type(self._query) is str
|
|
69
69
|
|
|
70
70
|
msg = []
|
|
71
71
|
|
|
@@ -76,17 +76,17 @@ class QueryException(TestgresException):
|
|
|
76
76
|
msg.append(u'Query: {}'.format(self._query))
|
|
77
77
|
|
|
78
78
|
r = six.text_type('\n').join(msg)
|
|
79
|
-
assert type(r)
|
|
79
|
+
assert type(r) is str
|
|
80
80
|
return r
|
|
81
81
|
|
|
82
82
|
@property
|
|
83
83
|
def description(self) -> typing.Optional[str]:
|
|
84
|
-
assert self._description is None or type(self._description)
|
|
84
|
+
assert self._description is None or type(self._description) is str
|
|
85
85
|
return self._description
|
|
86
86
|
|
|
87
87
|
@property
|
|
88
88
|
def query(self) -> typing.Optional[str]:
|
|
89
|
-
assert self._query is None or type(self._query)
|
|
89
|
+
assert self._query is None or type(self._query) is str
|
|
90
90
|
return self._query
|
|
91
91
|
|
|
92
92
|
def __repr__(self) -> str:
|
|
@@ -114,8 +114,8 @@ class QueryTimeoutException(QueryException):
|
|
|
114
114
|
message: typing.Optional[str] = None,
|
|
115
115
|
query: typing.Optional[str] = None
|
|
116
116
|
):
|
|
117
|
-
assert message is None or type(message)
|
|
118
|
-
assert query is None or type(query)
|
|
117
|
+
assert message is None or type(message) is str
|
|
118
|
+
assert query is None or type(query) is str
|
|
119
119
|
|
|
120
120
|
super().__init__(message, query)
|
|
121
121
|
return
|
|
@@ -133,14 +133,14 @@ class CatchUpException(TestgresException):
|
|
|
133
133
|
self,
|
|
134
134
|
message: typing.Optional[str] = None,
|
|
135
135
|
):
|
|
136
|
-
assert message is None or type(message)
|
|
136
|
+
assert message is None or type(message) is str
|
|
137
137
|
super().__init__(message)
|
|
138
138
|
self._message = message
|
|
139
139
|
return
|
|
140
140
|
|
|
141
141
|
@property
|
|
142
142
|
def message(self) -> str:
|
|
143
|
-
assert self._message is None or type(self._message)
|
|
143
|
+
assert self._message is None or type(self._message) is str
|
|
144
144
|
if self._message is None:
|
|
145
145
|
return ""
|
|
146
146
|
return self._message
|
|
@@ -171,7 +171,7 @@ class StartNodeException(TestgresException):
|
|
|
171
171
|
message: typing.Optional[str] = None,
|
|
172
172
|
files: typing.Optional[typing.Iterable] = None
|
|
173
173
|
):
|
|
174
|
-
assert message is None or type(message)
|
|
174
|
+
assert message is None or type(message) is str
|
|
175
175
|
assert files is None or isinstance(files, typing.Iterable)
|
|
176
176
|
|
|
177
177
|
super().__init__(message)
|
|
@@ -182,7 +182,7 @@ class StartNodeException(TestgresException):
|
|
|
182
182
|
|
|
183
183
|
@property
|
|
184
184
|
def message(self) -> str:
|
|
185
|
-
assert self._description is None or type(self._description)
|
|
185
|
+
assert self._description is None or type(self._description) is str
|
|
186
186
|
assert self._files is None or isinstance(self._files, typing.Iterable)
|
|
187
187
|
|
|
188
188
|
msg = []
|
|
@@ -191,15 +191,15 @@ class StartNodeException(TestgresException):
|
|
|
191
191
|
msg.append(self._description)
|
|
192
192
|
|
|
193
193
|
for f, lines in self._files or []:
|
|
194
|
-
assert type(f)
|
|
195
|
-
assert type(lines) in [str, bytes]
|
|
194
|
+
assert type(f) is str
|
|
195
|
+
assert type(lines) in [str, bytes]
|
|
196
196
|
msg.append(u'{}\n----\n{}\n'.format(f, lines))
|
|
197
197
|
|
|
198
198
|
return six.text_type('\n').join(msg)
|
|
199
199
|
|
|
200
200
|
@property
|
|
201
201
|
def description(self) -> typing.Optional[str]:
|
|
202
|
-
assert self._description is None or type(self._description)
|
|
202
|
+
assert self._description is None or type(self._description) is str
|
|
203
203
|
return self._description
|
|
204
204
|
|
|
205
205
|
@property
|
|
@@ -233,14 +233,14 @@ class InitNodeException(TestgresException):
|
|
|
233
233
|
self,
|
|
234
234
|
message: typing.Optional[str] = None,
|
|
235
235
|
):
|
|
236
|
-
assert message is None or type(message)
|
|
236
|
+
assert message is None or type(message) is str
|
|
237
237
|
super().__init__(message)
|
|
238
238
|
self._message = message
|
|
239
239
|
return
|
|
240
240
|
|
|
241
241
|
@property
|
|
242
242
|
def message(self) -> str:
|
|
243
|
-
assert self._message is None or type(self._message)
|
|
243
|
+
assert self._message is None or type(self._message) is str
|
|
244
244
|
if self._message is None:
|
|
245
245
|
return ""
|
|
246
246
|
return self._message
|
|
@@ -268,14 +268,14 @@ class BackupException(TestgresException):
|
|
|
268
268
|
self,
|
|
269
269
|
message: typing.Optional[str] = None,
|
|
270
270
|
):
|
|
271
|
-
assert message is None or type(message)
|
|
271
|
+
assert message is None or type(message) is str
|
|
272
272
|
super().__init__(message)
|
|
273
273
|
self._message = message
|
|
274
274
|
return
|
|
275
275
|
|
|
276
276
|
@property
|
|
277
277
|
def message(self) -> str:
|
|
278
|
-
assert self._message is None or type(self._message)
|
|
278
|
+
assert self._message is None or type(self._message) is str
|
|
279
279
|
if self._message is None:
|
|
280
280
|
return ""
|
|
281
281
|
return self._message
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def send_log(level: int, msg: str) -> None:
|
|
5
|
+
assert type(level) is int
|
|
6
|
+
assert type(msg) is str
|
|
7
|
+
|
|
8
|
+
return logging.log(level, "[testgres] " + msg)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def send_log_info(msg: str) -> None:
|
|
12
|
+
assert type(msg) is str
|
|
13
|
+
|
|
14
|
+
return send_log(logging.INFO, msg)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def send_log_debug(msg: str) -> None:
|
|
18
|
+
assert type(msg) is str
|
|
19
|
+
|
|
20
|
+
return send_log(logging.DEBUG, msg)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import enum
|
|
4
|
+
import typing
|
|
5
|
+
|
|
6
|
+
from testgres.operations.os_ops import OsOperations
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class InternalPlatformUtils:
|
|
10
|
+
class FindPostmasterResultCode(enum.Enum):
|
|
11
|
+
ok = 0
|
|
12
|
+
not_found = 1,
|
|
13
|
+
not_implemented = 2
|
|
14
|
+
many_processes = 3
|
|
15
|
+
has_problems = 4
|
|
16
|
+
|
|
17
|
+
class FindPostmasterResult:
|
|
18
|
+
code: InternalPlatformUtils.FindPostmasterResultCode
|
|
19
|
+
pid: typing.Optional[int]
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
code: InternalPlatformUtils.FindPostmasterResultCode,
|
|
24
|
+
pid: typing.Optional[int]
|
|
25
|
+
):
|
|
26
|
+
assert type(code) is InternalPlatformUtils.FindPostmasterResultCode
|
|
27
|
+
assert pid is None or type(pid) is int
|
|
28
|
+
self.code = code
|
|
29
|
+
self.pid = pid
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def create_ok(pid: int) -> InternalPlatformUtils.FindPostmasterResult:
|
|
34
|
+
assert type(pid) is int
|
|
35
|
+
return __class__(InternalPlatformUtils.FindPostmasterResultCode.ok, pid)
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def create_not_found() -> InternalPlatformUtils.FindPostmasterResult:
|
|
39
|
+
return __class__(InternalPlatformUtils.FindPostmasterResultCode.not_found, None)
|
|
40
|
+
|
|
41
|
+
@staticmethod
|
|
42
|
+
def create_not_implemented() -> InternalPlatformUtils.FindPostmasterResult:
|
|
43
|
+
return __class__(InternalPlatformUtils.FindPostmasterResultCode.not_implemented, None)
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def create_many_processes() -> InternalPlatformUtils.FindPostmasterResult:
|
|
47
|
+
return __class__(InternalPlatformUtils.FindPostmasterResultCode.many_processes, None)
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def create_has_problems() -> InternalPlatformUtils.FindPostmasterResult:
|
|
51
|
+
return __class__(InternalPlatformUtils.FindPostmasterResultCode.has_problems, None)
|
|
52
|
+
|
|
53
|
+
def FindPostmaster(
|
|
54
|
+
self,
|
|
55
|
+
os_ops: OsOperations,
|
|
56
|
+
bin_dir: str,
|
|
57
|
+
data_dir: str
|
|
58
|
+
) -> FindPostmasterResult:
|
|
59
|
+
assert isinstance(os_ops, OsOperations)
|
|
60
|
+
assert type(bin_dir) is str
|
|
61
|
+
assert type(data_dir) is str
|
|
62
|
+
raise NotImplementedError("InternalPlatformUtils::FindPostmaster is not implemented.")
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from .internal_platform_utils import InternalPlatformUtils
|
|
2
|
+
|
|
3
|
+
from testgres.operations.os_ops import OsOperations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def create_internal_platform_utils(
|
|
7
|
+
os_ops: OsOperations
|
|
8
|
+
) -> InternalPlatformUtils:
|
|
9
|
+
assert isinstance(os_ops, OsOperations)
|
|
10
|
+
|
|
11
|
+
platform_name = os_ops.get_platform()
|
|
12
|
+
assert type(platform_name) is str
|
|
13
|
+
|
|
14
|
+
if platform_name == "linux":
|
|
15
|
+
from .linux import internal_platform_utils as x
|
|
16
|
+
return x.InternalPlatformUtils()
|
|
17
|
+
|
|
18
|
+
if platform_name == "win32":
|
|
19
|
+
from .win32 import internal_platform_utils as x
|
|
20
|
+
return x.InternalPlatformUtils()
|
|
21
|
+
|
|
22
|
+
# not implemented
|
|
23
|
+
return InternalPlatformUtils()
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .. import internal_platform_utils as base
|
|
4
|
+
from ... import internal_utils
|
|
5
|
+
|
|
6
|
+
from testgres.operations.os_ops import OsOperations
|
|
7
|
+
from testgres.operations.exceptions import ExecUtilException
|
|
8
|
+
|
|
9
|
+
import re
|
|
10
|
+
import shlex
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class InternalPlatformUtils(base.InternalPlatformUtils):
|
|
14
|
+
C_BASH_EXE = "/bin/bash"
|
|
15
|
+
|
|
16
|
+
sm_exec_env = {
|
|
17
|
+
"LANG": "en_US.UTF-8",
|
|
18
|
+
"LC_ALL": "en_US.UTF-8",
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# --------------------------------------------------------------------
|
|
22
|
+
def FindPostmaster(
|
|
23
|
+
self,
|
|
24
|
+
os_ops: OsOperations,
|
|
25
|
+
bin_dir: str,
|
|
26
|
+
data_dir: str
|
|
27
|
+
) -> InternalPlatformUtils.FindPostmasterResult:
|
|
28
|
+
assert isinstance(os_ops, OsOperations)
|
|
29
|
+
assert type(bin_dir) is str
|
|
30
|
+
assert type(data_dir) is str
|
|
31
|
+
assert type(__class__.C_BASH_EXE) is str
|
|
32
|
+
assert type(__class__.sm_exec_env) is dict
|
|
33
|
+
assert len(__class__.C_BASH_EXE) > 0
|
|
34
|
+
assert len(bin_dir) > 0
|
|
35
|
+
assert len(data_dir) > 0
|
|
36
|
+
|
|
37
|
+
pg_path_e = re.escape(os_ops.build_path(bin_dir, "postgres"))
|
|
38
|
+
data_dir_e = re.escape(data_dir)
|
|
39
|
+
|
|
40
|
+
assert type(pg_path_e) is str
|
|
41
|
+
assert type(data_dir_e) is str
|
|
42
|
+
|
|
43
|
+
regexp = r"^\s*[0-9]+\s+" + pg_path_e + r"(\s+.*)?\s+\-[D]\s+" + data_dir_e + r"(\s+.*)?"
|
|
44
|
+
|
|
45
|
+
cmd = [
|
|
46
|
+
__class__.C_BASH_EXE,
|
|
47
|
+
"-c",
|
|
48
|
+
"ps -ewwo \"pid=,args=\" | grep -E " + shlex.quote(regexp),
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
exit_status, output_b, error_b = os_ops.exec_command(
|
|
52
|
+
cmd=cmd,
|
|
53
|
+
ignore_errors=True,
|
|
54
|
+
verbose=True,
|
|
55
|
+
exec_env=__class__.sm_exec_env,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
assert type(output_b) is bytes
|
|
59
|
+
assert type(error_b) is bytes
|
|
60
|
+
|
|
61
|
+
output = output_b.decode("utf-8")
|
|
62
|
+
error = error_b.decode("utf-8")
|
|
63
|
+
|
|
64
|
+
assert type(output) is str
|
|
65
|
+
assert type(error) is str
|
|
66
|
+
|
|
67
|
+
if exit_status == 1:
|
|
68
|
+
return __class__.FindPostmasterResult.create_not_found()
|
|
69
|
+
|
|
70
|
+
if exit_status != 0:
|
|
71
|
+
errMsg = f"test command returned an unexpected exit code: {exit_status}"
|
|
72
|
+
raise ExecUtilException(
|
|
73
|
+
message=errMsg,
|
|
74
|
+
command=cmd,
|
|
75
|
+
exit_code=exit_status,
|
|
76
|
+
out=output,
|
|
77
|
+
error=error,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
lines = output.splitlines()
|
|
81
|
+
assert type(lines) is list
|
|
82
|
+
|
|
83
|
+
if len(lines) == 0:
|
|
84
|
+
return __class__.FindPostmasterResult.create_not_found()
|
|
85
|
+
|
|
86
|
+
if len(lines) > 1:
|
|
87
|
+
msgs = []
|
|
88
|
+
msgs.append("Many processes like a postmaster are found: {}.".format(len(lines)))
|
|
89
|
+
|
|
90
|
+
for i in range(len(lines)):
|
|
91
|
+
assert type(lines[i]) is str
|
|
92
|
+
lines.append("[{}] '{}'".format(i, lines[i]))
|
|
93
|
+
continue
|
|
94
|
+
|
|
95
|
+
internal_utils.send_log_debug("\n".join(lines))
|
|
96
|
+
return __class__.FindPostmasterResult.create_many_processes()
|
|
97
|
+
|
|
98
|
+
def is_space_or_tab(ch) -> bool:
|
|
99
|
+
assert type(ch) is str
|
|
100
|
+
return ch == " " or ch == "\t"
|
|
101
|
+
|
|
102
|
+
line = lines[0]
|
|
103
|
+
start = 0
|
|
104
|
+
while start < len(line) and is_space_or_tab(line[start]):
|
|
105
|
+
start += 1
|
|
106
|
+
|
|
107
|
+
pos = start
|
|
108
|
+
while pos < len(line) and line[pos].isnumeric():
|
|
109
|
+
pos += 1
|
|
110
|
+
|
|
111
|
+
if pos == start:
|
|
112
|
+
return __class__.FindPostmasterResult.create_has_problems()
|
|
113
|
+
|
|
114
|
+
if pos != len(line) and not line[pos].isspace():
|
|
115
|
+
return __class__.FindPostmasterResult.create_has_problems()
|
|
116
|
+
|
|
117
|
+
pid = int(line[start:pos])
|
|
118
|
+
assert type(pid) is int
|
|
119
|
+
|
|
120
|
+
return __class__.FindPostmasterResult.create_ok(pid)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .. import internal_platform_utils as base
|
|
4
|
+
from testgres.operations.os_ops import OsOperations
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class InternalPlatformUtils(base.InternalPlatformUtils):
|
|
8
|
+
def FindPostmaster(
|
|
9
|
+
self,
|
|
10
|
+
os_ops: OsOperations,
|
|
11
|
+
bin_dir: str,
|
|
12
|
+
data_dir: str
|
|
13
|
+
) -> InternalPlatformUtils.FindPostmasterResult:
|
|
14
|
+
assert isinstance(os_ops, OsOperations)
|
|
15
|
+
assert type(bin_dir) is str
|
|
16
|
+
assert type(data_dir) is str
|
|
17
|
+
return __class__.FindPostmasterResult.create_not_implemented()
|
|
@@ -38,8 +38,8 @@ class PortManager__Generic(PortManager):
|
|
|
38
38
|
|
|
39
39
|
def reserve_port(self) -> int:
|
|
40
40
|
assert self._guard is not None
|
|
41
|
-
assert type(self._available_ports)
|
|
42
|
-
assert type(self._reserved_ports)
|
|
41
|
+
assert type(self._available_ports) is set
|
|
42
|
+
assert type(self._reserved_ports) is set
|
|
43
43
|
|
|
44
44
|
with self._guard:
|
|
45
45
|
t = tuple(self._available_ports)
|
|
@@ -48,8 +48,8 @@ class PortManager__Generic(PortManager):
|
|
|
48
48
|
t = None
|
|
49
49
|
|
|
50
50
|
for port in sampled_ports:
|
|
51
|
-
assert type(port)
|
|
52
|
-
assert not
|
|
51
|
+
assert type(port) is int
|
|
52
|
+
assert port not in self._reserved_ports
|
|
53
53
|
assert port in self._available_ports
|
|
54
54
|
|
|
55
55
|
assert port >= __class__._C_MIN_PORT_NUMBER
|
|
@@ -61,26 +61,26 @@ class PortManager__Generic(PortManager):
|
|
|
61
61
|
self._reserved_ports.add(port)
|
|
62
62
|
self._available_ports.discard(port)
|
|
63
63
|
assert port in self._reserved_ports
|
|
64
|
-
assert not
|
|
64
|
+
assert port not in self._available_ports
|
|
65
65
|
__class__.helper__send_debug_msg("Port {} is reserved.", port)
|
|
66
66
|
return port
|
|
67
67
|
|
|
68
68
|
raise PortForException("Can't select a port.")
|
|
69
69
|
|
|
70
70
|
def release_port(self, number: int) -> None:
|
|
71
|
-
assert type(number)
|
|
71
|
+
assert type(number) is int
|
|
72
72
|
assert number >= __class__._C_MIN_PORT_NUMBER
|
|
73
73
|
assert number <= __class__._C_MAX_PORT_NUMBER
|
|
74
74
|
|
|
75
75
|
assert self._guard is not None
|
|
76
|
-
assert type(self._reserved_ports)
|
|
76
|
+
assert type(self._reserved_ports) is set
|
|
77
77
|
|
|
78
78
|
with self._guard:
|
|
79
79
|
assert number in self._reserved_ports
|
|
80
|
-
assert not
|
|
80
|
+
assert number not in self._available_ports
|
|
81
81
|
self._available_ports.add(number)
|
|
82
82
|
self._reserved_ports.discard(number)
|
|
83
|
-
assert not
|
|
83
|
+
assert number not in self._reserved_ports
|
|
84
84
|
assert number in self._available_ports
|
|
85
85
|
__class__.helper__send_debug_msg("Port {} is released.", number)
|
|
86
86
|
return
|
|
@@ -89,8 +89,8 @@ class PortManager__Generic(PortManager):
|
|
|
89
89
|
def helper__send_debug_msg(msg_template: str, *args) -> None:
|
|
90
90
|
assert msg_template is not None
|
|
91
91
|
assert args is not None
|
|
92
|
-
assert type(msg_template)
|
|
93
|
-
assert type(args)
|
|
92
|
+
assert type(msg_template) is str
|
|
93
|
+
assert type(args) is tuple
|
|
94
94
|
assert msg_template != ""
|
|
95
95
|
s = "[port manager] "
|
|
96
96
|
s += msg_template.format(*args)
|
|
@@ -15,19 +15,19 @@ class PortManager__ThisHost(PortManager):
|
|
|
15
15
|
assert __class__.sm_single_instance_guard is not None
|
|
16
16
|
|
|
17
17
|
if __class__.sm_single_instance is not None:
|
|
18
|
-
assert type(__class__.sm_single_instance)
|
|
18
|
+
assert type(__class__.sm_single_instance) is __class__
|
|
19
19
|
return __class__.sm_single_instance
|
|
20
20
|
|
|
21
21
|
with __class__.sm_single_instance_guard:
|
|
22
22
|
if __class__.sm_single_instance is None:
|
|
23
23
|
__class__.sm_single_instance = __class__()
|
|
24
24
|
assert __class__.sm_single_instance is not None
|
|
25
|
-
assert type(__class__.sm_single_instance)
|
|
25
|
+
assert type(__class__.sm_single_instance) is __class__
|
|
26
26
|
return __class__.sm_single_instance
|
|
27
27
|
|
|
28
28
|
def reserve_port(self) -> int:
|
|
29
29
|
return utils.reserve_port()
|
|
30
30
|
|
|
31
31
|
def release_port(self, number: int) -> None:
|
|
32
|
-
assert type(number)
|
|
32
|
+
assert type(number) is int
|
|
33
33
|
return utils.release_port(number)
|