testgres 1.12.0__tar.gz → 1.12.2__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.12.0/testgres.egg-info → testgres-1.12.2}/PKG-INFO +2 -2
- {testgres-1.12.0 → testgres-1.12.2}/setup.py +2 -2
- {testgres-1.12.0 → testgres-1.12.2}/src/node.py +8 -6
- {testgres-1.12.0 → testgres-1.12.2/testgres.egg-info}/PKG-INFO +2 -2
- {testgres-1.12.0 → testgres-1.12.2}/testgres.egg-info/requires.txt +1 -1
- {testgres-1.12.0 → testgres-1.12.2}/tests/test_os_ops_common.py +199 -0
- {testgres-1.12.0 → testgres-1.12.2}/LICENSE +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/MANIFEST.in +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/README.md +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/setup.cfg +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/__init__.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/api.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/backup.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/cache.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/config.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/connection.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/consts.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/decorators.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/defaults.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/enums.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/exceptions.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/impl/port_manager__generic.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/impl/port_manager__this_host.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/logger.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/node_app.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/port_manager.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/pubsub.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/standby.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/src/utils.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/testgres.egg-info/SOURCES.txt +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/testgres.egg-info/dependency_links.txt +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/testgres.egg-info/top_level.txt +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/tests/__init__.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/tests/conftest.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/tests/helpers/__init__.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/tests/helpers/global_data.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/tests/helpers/run_conditions.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/tests/test_config.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/tests/test_os_ops_local.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/tests/test_os_ops_remote.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/tests/test_testgres_common.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/tests/test_testgres_local.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/tests/test_testgres_remote.py +0 -0
- {testgres-1.12.0 → testgres-1.12.2}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: testgres
|
|
3
|
-
Version: 1.12.
|
|
3
|
+
Version: 1.12.2
|
|
4
4
|
Summary: Testing utility for PostgreSQL and its extensions
|
|
5
5
|
Home-page: https://github.com/postgrespro/testgres
|
|
6
6
|
Author: Postgres Professional
|
|
@@ -14,7 +14,7 @@ Requires-Dist: port-for>=0.4
|
|
|
14
14
|
Requires-Dist: six>=1.9.0
|
|
15
15
|
Requires-Dist: psutil
|
|
16
16
|
Requires-Dist: packaging
|
|
17
|
-
Requires-Dist: testgres.os_ops<
|
|
17
|
+
Requires-Dist: testgres.os_ops<2.0.0,>=1.0.0
|
|
18
18
|
Dynamic: author
|
|
19
19
|
Dynamic: author-email
|
|
20
20
|
Dynamic: description
|
|
@@ -12,7 +12,7 @@ install_requires = [
|
|
|
12
12
|
"six>=1.9.0",
|
|
13
13
|
"psutil",
|
|
14
14
|
"packaging",
|
|
15
|
-
"testgres.os_ops>=0.0
|
|
15
|
+
"testgres.os_ops>=1.0.0,<2.0.0"
|
|
16
16
|
]
|
|
17
17
|
|
|
18
18
|
# Add compatibility enum class
|
|
@@ -28,7 +28,7 @@ with open('README.md', 'r') as f:
|
|
|
28
28
|
readme = f.read()
|
|
29
29
|
|
|
30
30
|
setup(
|
|
31
|
-
version='1.12.
|
|
31
|
+
version='1.12.2',
|
|
32
32
|
name='testgres',
|
|
33
33
|
packages=['testgres', 'testgres.impl'],
|
|
34
34
|
package_dir={"testgres": "src"},
|
|
@@ -669,7 +669,7 @@ class PostgresNode(object):
|
|
|
669
669
|
|
|
670
670
|
try:
|
|
671
671
|
eprint('Force stopping node {0} with PID {1}'.format(self.name, node_pid))
|
|
672
|
-
self.os_ops.kill(node_pid, signal.SIGKILL
|
|
672
|
+
self.os_ops.kill(node_pid, signal.SIGKILL)
|
|
673
673
|
except Exception:
|
|
674
674
|
# The node has already stopped
|
|
675
675
|
pass
|
|
@@ -1206,11 +1206,12 @@ class PostgresNode(object):
|
|
|
1206
1206
|
If None, the main PostgreSQL node process will be killed. Defaults to None.
|
|
1207
1207
|
"""
|
|
1208
1208
|
if self.is_started:
|
|
1209
|
+
assert isinstance(self._os_ops, OsOperations)
|
|
1209
1210
|
sig = signal.SIGKILL if os.name != 'nt' else signal.SIGBREAK
|
|
1210
1211
|
if someone is None:
|
|
1211
|
-
|
|
1212
|
+
self._os_ops.kill(self.pid, sig)
|
|
1212
1213
|
else:
|
|
1213
|
-
|
|
1214
|
+
self._os_ops.kill(self.auxiliary_pids[someone][0], sig)
|
|
1214
1215
|
self.is_started = False
|
|
1215
1216
|
|
|
1216
1217
|
def restart(self, params=[]):
|
|
@@ -2119,10 +2120,11 @@ class PostgresNode(object):
|
|
|
2119
2120
|
Args:
|
|
2120
2121
|
old_node: An instance of PostgresNode representing the old node.
|
|
2121
2122
|
"""
|
|
2122
|
-
|
|
2123
|
+
assert isinstance(self._os_ops, OsOperations)
|
|
2124
|
+
if not self._os_ops.path_exists(old_node.data_dir):
|
|
2123
2125
|
raise Exception("Old node must be initialized")
|
|
2124
2126
|
|
|
2125
|
-
if not
|
|
2127
|
+
if not self._os_ops.path_exists(self.data_dir):
|
|
2126
2128
|
self.init()
|
|
2127
2129
|
|
|
2128
2130
|
if not options:
|
|
@@ -2130,7 +2132,7 @@ class PostgresNode(object):
|
|
|
2130
2132
|
|
|
2131
2133
|
pg_upgrade_binary = self._get_bin_path("pg_upgrade")
|
|
2132
2134
|
|
|
2133
|
-
if not
|
|
2135
|
+
if not self._os_ops.path_exists(pg_upgrade_binary):
|
|
2134
2136
|
raise Exception("pg_upgrade does not exist in the new node's binary path")
|
|
2135
2137
|
|
|
2136
2138
|
upgrade_command = [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: testgres
|
|
3
|
-
Version: 1.12.
|
|
3
|
+
Version: 1.12.2
|
|
4
4
|
Summary: Testing utility for PostgreSQL and its extensions
|
|
5
5
|
Home-page: https://github.com/postgrespro/testgres
|
|
6
6
|
Author: Postgres Professional
|
|
@@ -14,7 +14,7 @@ Requires-Dist: port-for>=0.4
|
|
|
14
14
|
Requires-Dist: six>=1.9.0
|
|
15
15
|
Requires-Dist: psutil
|
|
16
16
|
Requires-Dist: packaging
|
|
17
|
-
Requires-Dist: testgres.os_ops<
|
|
17
|
+
Requires-Dist: testgres.os_ops<2.0.0,>=1.0.0
|
|
18
18
|
Dynamic: author
|
|
19
19
|
Dynamic: author-email
|
|
20
20
|
Dynamic: description
|
|
@@ -5,6 +5,7 @@ from .helpers.global_data import OsOperations
|
|
|
5
5
|
from .helpers.run_conditions import RunConditions
|
|
6
6
|
|
|
7
7
|
import os
|
|
8
|
+
import sys
|
|
8
9
|
|
|
9
10
|
import pytest
|
|
10
11
|
import re
|
|
@@ -14,6 +15,10 @@ import socket
|
|
|
14
15
|
import threading
|
|
15
16
|
import typing
|
|
16
17
|
import uuid
|
|
18
|
+
import subprocess
|
|
19
|
+
import psutil
|
|
20
|
+
import time
|
|
21
|
+
import signal as os_signal
|
|
17
22
|
|
|
18
23
|
from src import InvalidOperationException
|
|
19
24
|
from src import ExecUtilException
|
|
@@ -1137,3 +1142,197 @@ class TestOsOpsCommon:
|
|
|
1137
1142
|
|
|
1138
1143
|
logging.info("Test is finished! Total error count is {}.".format(nErrors))
|
|
1139
1144
|
return
|
|
1145
|
+
|
|
1146
|
+
T_KILL_SIGNAL_DESCR = typing.Tuple[
|
|
1147
|
+
str,
|
|
1148
|
+
typing.Union[int, os_signal.Signals],
|
|
1149
|
+
str
|
|
1150
|
+
]
|
|
1151
|
+
|
|
1152
|
+
sm_kill_signal_ids: typing.List[T_KILL_SIGNAL_DESCR] = [
|
|
1153
|
+
("SIGINT", os_signal.SIGINT, "2"),
|
|
1154
|
+
# ("SIGQUIT", os_signal.SIGQUIT, "3"), # it creates coredump
|
|
1155
|
+
("SIGKILL", os_signal.SIGKILL, "9"),
|
|
1156
|
+
("SIGTERM", os_signal.SIGTERM, "15"),
|
|
1157
|
+
("2", 2, "2"),
|
|
1158
|
+
# ("3", 3, "3"), # it creates coredump
|
|
1159
|
+
("9", 9, "9"),
|
|
1160
|
+
("15", 15, "15"),
|
|
1161
|
+
]
|
|
1162
|
+
|
|
1163
|
+
@pytest.fixture(
|
|
1164
|
+
params=sm_kill_signal_ids,
|
|
1165
|
+
ids=["signal: {}".format(x[0]) for x in sm_kill_signal_ids],
|
|
1166
|
+
)
|
|
1167
|
+
def kill_signal_id(self, request: pytest.FixtureRequest) -> T_KILL_SIGNAL_DESCR:
|
|
1168
|
+
assert isinstance(request, pytest.FixtureRequest)
|
|
1169
|
+
assert type(request.param) == tuple # noqa: E721
|
|
1170
|
+
return request.param
|
|
1171
|
+
|
|
1172
|
+
def test_kill_signal(
|
|
1173
|
+
self,
|
|
1174
|
+
kill_signal_id: T_KILL_SIGNAL_DESCR,
|
|
1175
|
+
):
|
|
1176
|
+
assert type(kill_signal_id) == tuple # noqa: E721
|
|
1177
|
+
assert "{}".format(kill_signal_id[1]) == kill_signal_id[2]
|
|
1178
|
+
assert "{}".format(int(kill_signal_id[1])) == kill_signal_id[2]
|
|
1179
|
+
|
|
1180
|
+
def test_kill(
|
|
1181
|
+
self,
|
|
1182
|
+
os_ops: OsOperations,
|
|
1183
|
+
kill_signal_id: T_KILL_SIGNAL_DESCR,
|
|
1184
|
+
):
|
|
1185
|
+
"""
|
|
1186
|
+
Test listdir for listing directory contents.
|
|
1187
|
+
"""
|
|
1188
|
+
assert isinstance(os_ops, OsOperations)
|
|
1189
|
+
assert type(kill_signal_id) == tuple # noqa: E721
|
|
1190
|
+
|
|
1191
|
+
cmd = [
|
|
1192
|
+
sys.executable,
|
|
1193
|
+
"-c",
|
|
1194
|
+
"import time; print('ENTER');time.sleep(300);print('EXIT')"
|
|
1195
|
+
]
|
|
1196
|
+
|
|
1197
|
+
logging.info("Local test process is creating ...")
|
|
1198
|
+
proc = subprocess.Popen(
|
|
1199
|
+
cmd,
|
|
1200
|
+
text=True,
|
|
1201
|
+
)
|
|
1202
|
+
|
|
1203
|
+
assert proc is not None
|
|
1204
|
+
assert type(proc) == subprocess.Popen # noqa: E721
|
|
1205
|
+
proc_pid = proc.pid
|
|
1206
|
+
assert type(proc_pid) == int # noqa: E721
|
|
1207
|
+
logging.info("Test process pid is {}".format(proc_pid))
|
|
1208
|
+
|
|
1209
|
+
logging.info("Get this test process ...")
|
|
1210
|
+
p1 = psutil.Process(proc_pid)
|
|
1211
|
+
assert p1 is not None
|
|
1212
|
+
del p1
|
|
1213
|
+
|
|
1214
|
+
logging.info("Kill this test process ...")
|
|
1215
|
+
os_ops.kill(proc_pid, kill_signal_id[1])
|
|
1216
|
+
|
|
1217
|
+
logging.info("Wait for finish ...")
|
|
1218
|
+
proc.wait()
|
|
1219
|
+
|
|
1220
|
+
logging.info("Try to get this test process ...")
|
|
1221
|
+
|
|
1222
|
+
attempt = 0
|
|
1223
|
+
while True:
|
|
1224
|
+
if attempt == 20:
|
|
1225
|
+
raise RuntimeError("Process did not die.")
|
|
1226
|
+
|
|
1227
|
+
attempt += 1
|
|
1228
|
+
|
|
1229
|
+
if attempt > 1:
|
|
1230
|
+
logging.info("Sleep 1 seconds...")
|
|
1231
|
+
time.sleep(1)
|
|
1232
|
+
|
|
1233
|
+
try:
|
|
1234
|
+
psutil.Process(proc_pid)
|
|
1235
|
+
except psutil.ZombieProcess as e:
|
|
1236
|
+
logging.info("Exception {}: {}".format(
|
|
1237
|
+
type(e).__name__,
|
|
1238
|
+
str(e),
|
|
1239
|
+
))
|
|
1240
|
+
except psutil.NoSuchProcess:
|
|
1241
|
+
logging.info("OK. Process died.")
|
|
1242
|
+
break
|
|
1243
|
+
|
|
1244
|
+
logging.info("Process is alive!")
|
|
1245
|
+
continue
|
|
1246
|
+
|
|
1247
|
+
return
|
|
1248
|
+
|
|
1249
|
+
def test_kill__unk_pid(
|
|
1250
|
+
self,
|
|
1251
|
+
os_ops: OsOperations,
|
|
1252
|
+
kill_signal_id: T_KILL_SIGNAL_DESCR,
|
|
1253
|
+
):
|
|
1254
|
+
"""
|
|
1255
|
+
Test listdir for listing directory contents.
|
|
1256
|
+
"""
|
|
1257
|
+
assert isinstance(os_ops, OsOperations)
|
|
1258
|
+
assert type(kill_signal_id) == tuple # noqa: E721
|
|
1259
|
+
|
|
1260
|
+
cmd = [
|
|
1261
|
+
sys.executable,
|
|
1262
|
+
"-c",
|
|
1263
|
+
"import sys; print(\"a\", file=sys.stdout); print(\"b\", file=sys.stderr)"
|
|
1264
|
+
]
|
|
1265
|
+
|
|
1266
|
+
logging.info("Local test process is creating ...")
|
|
1267
|
+
proc = subprocess.Popen(
|
|
1268
|
+
cmd,
|
|
1269
|
+
text=True,
|
|
1270
|
+
stdout=subprocess.PIPE,
|
|
1271
|
+
stderr=subprocess.PIPE,
|
|
1272
|
+
)
|
|
1273
|
+
|
|
1274
|
+
assert proc is not None
|
|
1275
|
+
assert type(proc) == subprocess.Popen # noqa: E721
|
|
1276
|
+
proc_pid = proc.pid
|
|
1277
|
+
assert type(proc_pid) == int # noqa: E721
|
|
1278
|
+
logging.info("Test process pid is {}".format(proc_pid))
|
|
1279
|
+
|
|
1280
|
+
logging.info("Wait for finish ...")
|
|
1281
|
+
pout, perr = proc.communicate()
|
|
1282
|
+
logging.info("STDOUT: {}".format(pout))
|
|
1283
|
+
logging.info("STDERR: {}".format(pout))
|
|
1284
|
+
assert type(pout) == str # noqa: E721
|
|
1285
|
+
assert type(perr) == str # noqa: E721
|
|
1286
|
+
assert pout == "a\n"
|
|
1287
|
+
assert perr == "b\n"
|
|
1288
|
+
assert type(proc.returncode) == int # noqa: E721
|
|
1289
|
+
assert proc.returncode == 0
|
|
1290
|
+
|
|
1291
|
+
logging.info("Try to get this test process ...")
|
|
1292
|
+
|
|
1293
|
+
attempt = 0
|
|
1294
|
+
while True:
|
|
1295
|
+
if attempt == 20:
|
|
1296
|
+
raise RuntimeError("Process did not die.")
|
|
1297
|
+
|
|
1298
|
+
attempt += 1
|
|
1299
|
+
|
|
1300
|
+
if attempt > 1:
|
|
1301
|
+
logging.info("Sleep 1 seconds...")
|
|
1302
|
+
time.sleep(1)
|
|
1303
|
+
|
|
1304
|
+
try:
|
|
1305
|
+
psutil.Process(proc_pid)
|
|
1306
|
+
except psutil.ZombieProcess as e:
|
|
1307
|
+
logging.info("Exception {}: {}".format(
|
|
1308
|
+
type(e).__name__,
|
|
1309
|
+
str(e),
|
|
1310
|
+
))
|
|
1311
|
+
except psutil.NoSuchProcess:
|
|
1312
|
+
logging.info("OK. Process died.")
|
|
1313
|
+
break
|
|
1314
|
+
|
|
1315
|
+
logging.info("Process is alive!")
|
|
1316
|
+
continue
|
|
1317
|
+
|
|
1318
|
+
# --------------------
|
|
1319
|
+
with pytest.raises(expected_exception=Exception) as x:
|
|
1320
|
+
os_ops.kill(proc_pid, kill_signal_id[1])
|
|
1321
|
+
|
|
1322
|
+
assert x is not None
|
|
1323
|
+
assert isinstance(x.value, Exception)
|
|
1324
|
+
assert not isinstance(x.value, AssertionError)
|
|
1325
|
+
|
|
1326
|
+
logging.info("Our error is [{}]".format(str(x.value)))
|
|
1327
|
+
logging.info("Our exception has type [{}]".format(type(x.value).__name__))
|
|
1328
|
+
|
|
1329
|
+
if type(os_ops).__name__ == "LocalOsOperations":
|
|
1330
|
+
assert type(x.value) == ProcessLookupError # noqa: E721
|
|
1331
|
+
assert "No such process" in str(x.value)
|
|
1332
|
+
elif type(os_ops).__name__ == "RemoteOsOperations":
|
|
1333
|
+
assert type(x.value) == ExecUtilException # noqa: E721
|
|
1334
|
+
assert "No such process" in str(x.value)
|
|
1335
|
+
else:
|
|
1336
|
+
RuntimeError("Unknown os_ops type: {}".format(type(os_ops).__name__))
|
|
1337
|
+
|
|
1338
|
+
return
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|