testgres 1.15.0__tar.gz → 1.15.1__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.15.0/testgres.egg-info → testgres-1.15.1}/PKG-INFO +2 -2
- {testgres-1.15.0 → testgres-1.15.1}/pyproject.toml +1 -1
- {testgres-1.15.0 → testgres-1.15.1}/src/__init__.py +1 -1
- {testgres-1.15.0 → testgres-1.15.1}/src/impl/file_line_reader.py +9 -2
- testgres-1.15.1/src/impl/internal_utils.py +92 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/node.py +53 -13
- {testgres-1.15.0 → testgres-1.15.1/testgres.egg-info}/PKG-INFO +2 -2
- {testgres-1.15.0 → testgres-1.15.1}/testgres.egg-info/requires.txt +1 -1
- {testgres-1.15.0 → testgres-1.15.1}/tests/test_os_ops_common.py +16 -1
- {testgres-1.15.0 → testgres-1.15.1}/tests/test_testgres_common.py +91 -35
- {testgres-1.15.0 → testgres-1.15.1}/tests/test_testgres_remote.py +3 -0
- testgres-1.15.0/src/impl/internal_utils.py +0 -20
- {testgres-1.15.0 → testgres-1.15.1}/LICENSE +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/README.md +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/setup.cfg +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/api.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/backup.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/cache.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/config.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/connection.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/consts.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/decorators.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/defaults.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/enums.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/exceptions.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/impl/platforms/internal_platform_utils.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/impl/platforms/internal_platform_utils_factory.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/impl/platforms/linux/internal_platform_utils.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/impl/platforms/win32/internal_platform_utils.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/impl/port_manager__generic.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/impl/port_manager__generic2.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/impl/port_manager__this_host.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/logger.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/node_app.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/port_manager.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/pubsub.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/raise_error.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/standby.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/src/utils.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/testgres.egg-info/SOURCES.txt +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/testgres.egg-info/dependency_links.txt +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/testgres.egg-info/top_level.txt +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/tests/test_api.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/tests/test_config.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/tests/test_os_ops_local.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/tests/test_os_ops_remote.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/tests/test_raise_error.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/tests/test_testgres_local.py +0 -0
- {testgres-1.15.0 → testgres-1.15.1}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: testgres
|
|
3
|
-
Version: 1.15.
|
|
3
|
+
Version: 1.15.1
|
|
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<4.0.0,>=3.
|
|
30
|
+
Requires-Dist: testgres.os_ops<4.0.0,>=3.2.0
|
|
31
31
|
Dynamic: license-file
|
|
32
32
|
|
|
33
33
|
[](https://github.com/postgrespro/testgres/actions/workflows/ci.yml)
|
|
@@ -57,7 +57,7 @@ from testgres.operations.os_ops import OsOperations, ConnectionParams
|
|
|
57
57
|
from testgres.operations.local_ops import LocalOperations
|
|
58
58
|
from testgres.operations.remote_ops import RemoteOperations
|
|
59
59
|
|
|
60
|
-
__version__ = "1.15.
|
|
60
|
+
__version__ = "1.15.1"
|
|
61
61
|
|
|
62
62
|
__all__ = [
|
|
63
63
|
"get_new_node",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
|
|
3
|
+
from . import internal_utils
|
|
4
|
+
|
|
3
5
|
import typing
|
|
4
6
|
|
|
5
7
|
from testgres.operations.os_ops import OsOperations
|
|
@@ -19,15 +21,20 @@ class FileLineReader:
|
|
|
19
21
|
os_ops: OsOperations,
|
|
20
22
|
file_name: str,
|
|
21
23
|
file_encoding: str = "utf-8",
|
|
24
|
+
file_pos: int = 0
|
|
22
25
|
):
|
|
23
26
|
assert isinstance(os_ops, OsOperations)
|
|
24
27
|
assert type(file_encoding) is str
|
|
25
28
|
self._os_ops = os_ops
|
|
26
29
|
self._file_name = file_name
|
|
27
30
|
self._file_encoding = file_encoding
|
|
28
|
-
self._file_pos =
|
|
31
|
+
self._file_pos = file_pos
|
|
29
32
|
self._buffer_pos = 0
|
|
30
|
-
self._buffer =
|
|
33
|
+
self._buffer = internal_utils.read_line_to_pos__bin(
|
|
34
|
+
os_ops,
|
|
35
|
+
file_name,
|
|
36
|
+
file_pos,
|
|
37
|
+
)
|
|
31
38
|
return
|
|
32
39
|
|
|
33
40
|
# interface ----------------------------------------------------------
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from testgres.operations.os_ops import OsOperations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import typing
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def send_log(level: int, msg: str) -> None:
|
|
8
|
+
assert type(level) is int
|
|
9
|
+
assert type(msg) is str
|
|
10
|
+
|
|
11
|
+
return logging.log(level, "[testgres] " + msg)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def send_log_info(msg: str) -> None:
|
|
15
|
+
assert type(msg) is str
|
|
16
|
+
|
|
17
|
+
return send_log(logging.INFO, msg)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def send_log_debug(msg: str) -> None:
|
|
21
|
+
assert type(msg) is str
|
|
22
|
+
|
|
23
|
+
return send_log(logging.DEBUG, msg)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def read_line_to_pos__bin(
|
|
27
|
+
os_ops: OsOperations,
|
|
28
|
+
filename: str,
|
|
29
|
+
position: int,
|
|
30
|
+
) -> bytes:
|
|
31
|
+
assert type(filename) is str
|
|
32
|
+
assert type(position) is int
|
|
33
|
+
assert len(filename) > 0
|
|
34
|
+
assert position >= 0
|
|
35
|
+
assert os_ops is not None
|
|
36
|
+
assert isinstance(os_ops, OsOperations)
|
|
37
|
+
|
|
38
|
+
if position == 0:
|
|
39
|
+
return b''
|
|
40
|
+
|
|
41
|
+
assert position > 0
|
|
42
|
+
|
|
43
|
+
read_position = position
|
|
44
|
+
result_blocks: typing.List[bytes] = []
|
|
45
|
+
|
|
46
|
+
C_BACK_READ_BLOCK_SIZE = 4096
|
|
47
|
+
|
|
48
|
+
while read_position > 0:
|
|
49
|
+
if read_position < C_BACK_READ_BLOCK_SIZE:
|
|
50
|
+
block_sz = read_position
|
|
51
|
+
else:
|
|
52
|
+
block_sz = C_BACK_READ_BLOCK_SIZE
|
|
53
|
+
|
|
54
|
+
assert block_sz > 0
|
|
55
|
+
assert block_sz <= C_BACK_READ_BLOCK_SIZE
|
|
56
|
+
|
|
57
|
+
read_position -= block_sz
|
|
58
|
+
|
|
59
|
+
assert read_position < position
|
|
60
|
+
assert read_position >= 0
|
|
61
|
+
|
|
62
|
+
block = os_ops.read_binary(filename, read_position, block_sz)
|
|
63
|
+
|
|
64
|
+
assert type(block) is bytes
|
|
65
|
+
|
|
66
|
+
if len(block) != block_sz:
|
|
67
|
+
err_msg = "[BUG CHECK] Readed block has bad size ({}). Expected size is ({}). File name {}.".format(
|
|
68
|
+
len(block),
|
|
69
|
+
block_sz,
|
|
70
|
+
filename,
|
|
71
|
+
)
|
|
72
|
+
raise RuntimeError(err_msg)
|
|
73
|
+
|
|
74
|
+
assert len(block) == block_sz
|
|
75
|
+
|
|
76
|
+
x = block.rfind(b"\n", 0, block_sz)
|
|
77
|
+
|
|
78
|
+
if x == -1:
|
|
79
|
+
result_blocks.append(block)
|
|
80
|
+
continue
|
|
81
|
+
|
|
82
|
+
if x == block_sz - 1:
|
|
83
|
+
break
|
|
84
|
+
|
|
85
|
+
block = block[x + 1:]
|
|
86
|
+
result_blocks.append(block)
|
|
87
|
+
break
|
|
88
|
+
|
|
89
|
+
result = b''.join(reversed(result_blocks))
|
|
90
|
+
assert type(result) is bytes
|
|
91
|
+
assert len(result) <= (position - read_position)
|
|
92
|
+
return result
|
|
@@ -1278,7 +1278,7 @@ class PostgresNode(object):
|
|
|
1278
1278
|
if nAttempt == __class__._C_MAX_START_ATEMPTS:
|
|
1279
1279
|
self._raise_cannot_start_node(e, "Cannot start node after multiple attempts.")
|
|
1280
1280
|
|
|
1281
|
-
is_it_port_conflict = PostgresNodeUtils.
|
|
1281
|
+
is_it_port_conflict = PostgresNodeUtils.detect_port_conflict(log_reader)
|
|
1282
1282
|
|
|
1283
1283
|
if not is_it_port_conflict:
|
|
1284
1284
|
LOCAL__raise_cannot_start_node__std(e)
|
|
@@ -2430,9 +2430,14 @@ class PostgresNodeLogReader:
|
|
|
2430
2430
|
position: int
|
|
2431
2431
|
tail: bytes
|
|
2432
2432
|
|
|
2433
|
-
def __init__(self, position: int):
|
|
2433
|
+
def __init__(self, position: int, tail: bytes = b''):
|
|
2434
|
+
assert type(position) is int
|
|
2435
|
+
assert type(tail) is bytes
|
|
2436
|
+
assert position >= 0
|
|
2437
|
+
|
|
2434
2438
|
self.position = position
|
|
2435
|
-
self.tail =
|
|
2439
|
+
self.tail = tail
|
|
2440
|
+
return
|
|
2436
2441
|
|
|
2437
2442
|
# --------------------------------------------------------------------
|
|
2438
2443
|
class LogDataBlock:
|
|
@@ -2487,7 +2492,7 @@ class PostgresNodeLogReader:
|
|
|
2487
2492
|
if from_beginnig:
|
|
2488
2493
|
self._logs = dict()
|
|
2489
2494
|
else:
|
|
2490
|
-
self._logs = self._collect_logs()
|
|
2495
|
+
self._logs = self._collect_logs(find_line_start=True)
|
|
2491
2496
|
|
|
2492
2497
|
assert type(self._logs) is dict
|
|
2493
2498
|
return
|
|
@@ -2496,13 +2501,13 @@ class PostgresNodeLogReader:
|
|
|
2496
2501
|
assert self._node is not None
|
|
2497
2502
|
assert isinstance(self._node, PostgresNode)
|
|
2498
2503
|
|
|
2499
|
-
cur_logs
|
|
2504
|
+
cur_logs = self._collect_logs(find_line_start=False)
|
|
2500
2505
|
assert cur_logs is not None
|
|
2501
2506
|
assert type(cur_logs) is dict
|
|
2502
2507
|
|
|
2503
2508
|
assert type(self._logs) is dict
|
|
2504
2509
|
|
|
2505
|
-
result =
|
|
2510
|
+
result: typing.List[__class__.LogDataBlock] = []
|
|
2506
2511
|
|
|
2507
2512
|
for file_name, cur_log_info in cur_logs.items():
|
|
2508
2513
|
assert type(file_name) is str
|
|
@@ -2570,7 +2575,8 @@ class PostgresNodeLogReader:
|
|
|
2570
2575
|
|
|
2571
2576
|
return result
|
|
2572
2577
|
|
|
2573
|
-
def _collect_logs(self) -> typing.Dict[str, LogInfo]:
|
|
2578
|
+
def _collect_logs(self, find_line_start: bool) -> typing.Dict[str, LogInfo]:
|
|
2579
|
+
assert type(find_line_start) is bool
|
|
2574
2580
|
assert self._node is not None
|
|
2575
2581
|
assert isinstance(self._node, PostgresNode)
|
|
2576
2582
|
|
|
@@ -2587,18 +2593,52 @@ class PostgresNodeLogReader:
|
|
|
2587
2593
|
if not self._node.os_ops.path_exists(f):
|
|
2588
2594
|
continue
|
|
2589
2595
|
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2596
|
+
result[f] = self._create_log_info(
|
|
2597
|
+
self._node.os_ops,
|
|
2598
|
+
f,
|
|
2599
|
+
find_line_start,
|
|
2600
|
+
)
|
|
2601
|
+
continue
|
|
2595
2602
|
|
|
2596
2603
|
return result
|
|
2597
2604
|
|
|
2605
|
+
@staticmethod
|
|
2606
|
+
def _create_log_info(
|
|
2607
|
+
os_ops: OsOperations,
|
|
2608
|
+
filename: str,
|
|
2609
|
+
find_line_start: bool,
|
|
2610
|
+
) -> LogInfo:
|
|
2611
|
+
assert type(filename) is str
|
|
2612
|
+
assert type(find_line_start) is bool
|
|
2613
|
+
assert len(filename) > 0
|
|
2614
|
+
assert os_ops is not None
|
|
2615
|
+
assert isinstance(os_ops, OsOperations)
|
|
2616
|
+
|
|
2617
|
+
file_size = os_ops.get_file_size(filename)
|
|
2618
|
+
assert type(file_size) is int
|
|
2619
|
+
assert file_size >= 0
|
|
2620
|
+
|
|
2621
|
+
if not find_line_start:
|
|
2622
|
+
return __class__.LogInfo(
|
|
2623
|
+
position=file_size,
|
|
2624
|
+
tail=b'',
|
|
2625
|
+
)
|
|
2626
|
+
|
|
2627
|
+
tail = internal_utils.read_line_to_pos__bin(
|
|
2628
|
+
os_ops,
|
|
2629
|
+
filename,
|
|
2630
|
+
file_size,
|
|
2631
|
+
)
|
|
2632
|
+
|
|
2633
|
+
return __class__.LogInfo(
|
|
2634
|
+
position=file_size,
|
|
2635
|
+
tail=tail,
|
|
2636
|
+
)
|
|
2637
|
+
|
|
2598
2638
|
|
|
2599
2639
|
class PostgresNodeUtils:
|
|
2600
2640
|
@staticmethod
|
|
2601
|
-
def
|
|
2641
|
+
def detect_port_conflict(log_reader: PostgresNodeLogReader) -> bool:
|
|
2602
2642
|
assert type(log_reader) is PostgresNodeLogReader
|
|
2603
2643
|
|
|
2604
2644
|
blocks = log_reader.read()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: testgres
|
|
3
|
-
Version: 1.15.
|
|
3
|
+
Version: 1.15.1
|
|
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<4.0.0,>=3.
|
|
30
|
+
Requires-Dist: testgres.os_ops<4.0.0,>=3.2.0
|
|
31
31
|
Dynamic: license-file
|
|
32
32
|
|
|
33
33
|
[](https://github.com/postgrespro/testgres/actions/workflows/ci.yml)
|
|
@@ -1352,8 +1352,15 @@ class TestOsOpsCommon:
|
|
|
1352
1352
|
|
|
1353
1353
|
tmpdir = os_ops.get_tempdir()
|
|
1354
1354
|
|
|
1355
|
-
|
|
1355
|
+
filedir = os_ops.build_path(
|
|
1356
1356
|
tmpdir,
|
|
1357
|
+
"test_isfile_false__not_exist-" + uuid.uuid4().bytes.hex(),
|
|
1358
|
+
)
|
|
1359
|
+
|
|
1360
|
+
os_ops.makedir(filedir)
|
|
1361
|
+
|
|
1362
|
+
filename = os_ops.build_path(
|
|
1363
|
+
filedir,
|
|
1357
1364
|
name_with_surprize.value,
|
|
1358
1365
|
)
|
|
1359
1366
|
|
|
@@ -1369,7 +1376,11 @@ class TestOsOpsCommon:
|
|
|
1369
1376
|
pass
|
|
1370
1377
|
else:
|
|
1371
1378
|
# We will check a real work with another host
|
|
1379
|
+
assert not os.path.exists(filedir)
|
|
1372
1380
|
assert not os.path.exists(filename)
|
|
1381
|
+
|
|
1382
|
+
os.mkdir(filedir)
|
|
1383
|
+
|
|
1373
1384
|
with open(filename, "a"):
|
|
1374
1385
|
os.utime(filename, None)
|
|
1375
1386
|
assert os.path.exists(filename)
|
|
@@ -1384,7 +1395,11 @@ class TestOsOpsCommon:
|
|
|
1384
1395
|
assert os.path.exists(filename)
|
|
1385
1396
|
os.remove(filename)
|
|
1386
1397
|
assert not os.path.exists(filename)
|
|
1398
|
+
os.rmdir(filedir)
|
|
1399
|
+
assert not os.path.exists(filedir)
|
|
1387
1400
|
logging.info("Local detecter is deleted [{}]".format(filename))
|
|
1401
|
+
|
|
1402
|
+
os_ops.rmdir(filedir)
|
|
1388
1403
|
return
|
|
1389
1404
|
|
|
1390
1405
|
def test_isfile_false__directory(
|
|
@@ -121,7 +121,7 @@ class TestTestgresCommon:
|
|
|
121
121
|
# Author: Mark G.
|
|
122
122
|
assert v.major == 1
|
|
123
123
|
assert v.minor == 15
|
|
124
|
-
assert v.micro ==
|
|
124
|
+
assert v.micro == 1
|
|
125
125
|
|
|
126
126
|
assert str(v) == testgres_version
|
|
127
127
|
return
|
|
@@ -190,15 +190,15 @@ class TestTestgresCommon:
|
|
|
190
190
|
return
|
|
191
191
|
|
|
192
192
|
def test_node_constructor__default(self):
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
193
|
+
with PostgresNode() as node:
|
|
194
|
+
assert node._os_ops is not None
|
|
195
|
+
assert isinstance(node._os_ops, OsOperations)
|
|
196
|
+
assert node._port_manager is not None
|
|
197
|
+
assert isinstance(node._port_manager, PortManager)
|
|
198
|
+
assert node._name is not None
|
|
199
|
+
assert type(node._name) is str
|
|
200
|
+
assert node._name != ""
|
|
201
|
+
assert node._base_dir is None
|
|
202
202
|
return
|
|
203
203
|
|
|
204
204
|
def test_node_constructor__host(self):
|
|
@@ -456,12 +456,70 @@ class TestTestgresCommon:
|
|
|
456
456
|
assert isinstance(node_svc, PostgresNodeService)
|
|
457
457
|
|
|
458
458
|
with __class__.helper__get_node(node_svc) as node:
|
|
459
|
-
node.init()
|
|
459
|
+
node.init()
|
|
460
|
+
|
|
461
|
+
nRestartAttempt = 0
|
|
462
|
+
|
|
463
|
+
while True:
|
|
464
|
+
nRestartAttempt += 1
|
|
465
|
+
|
|
466
|
+
logging.info("Attempt #{}".format(nRestartAttempt))
|
|
467
|
+
|
|
468
|
+
node.start()
|
|
469
|
+
|
|
470
|
+
# restart, ok
|
|
471
|
+
res = node.execute('select 1')
|
|
472
|
+
assert (res == [(1,)])
|
|
473
|
+
|
|
474
|
+
node_log_reader = PostgresNodeLogReader(
|
|
475
|
+
node,
|
|
476
|
+
from_beginnig=False,
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
try:
|
|
480
|
+
node.restart()
|
|
481
|
+
except StartNodeException as e:
|
|
482
|
+
logging.info("Exception ({}): {}".format(
|
|
483
|
+
type(e).__name__,
|
|
484
|
+
e,
|
|
485
|
+
))
|
|
486
|
+
|
|
487
|
+
if nRestartAttempt == 5:
|
|
488
|
+
raise
|
|
489
|
+
|
|
490
|
+
if not PostgresNodeUtils.detect_port_conflict(node_log_reader):
|
|
491
|
+
raise
|
|
492
|
+
|
|
493
|
+
logging.info("Node port {} conflicted with another PostgreSQL instance.".format(
|
|
494
|
+
node.port
|
|
495
|
+
))
|
|
496
|
+
|
|
497
|
+
logging.info("Wait for node stop")
|
|
498
|
+
|
|
499
|
+
nStopAttemtp = 0
|
|
500
|
+
|
|
501
|
+
while True:
|
|
502
|
+
if nStopAttemtp == 5:
|
|
503
|
+
raise RuntimeError("Node is not stopped!")
|
|
504
|
+
|
|
505
|
+
nStopAttemtp += 1
|
|
506
|
+
|
|
507
|
+
time.sleep(1)
|
|
508
|
+
|
|
509
|
+
node_status = node.status()
|
|
510
|
+
|
|
511
|
+
logging.info("Node status is {}".format(node_status))
|
|
512
|
+
|
|
513
|
+
if node_status == NodeStatus.Stopped:
|
|
514
|
+
break
|
|
515
|
+
continue
|
|
516
|
+
|
|
517
|
+
# node is stopped. try again
|
|
518
|
+
continue
|
|
519
|
+
|
|
520
|
+
assert node.status() == NodeStatus.Running
|
|
521
|
+
break
|
|
460
522
|
|
|
461
|
-
# restart, ok
|
|
462
|
-
res = node.execute('select 1')
|
|
463
|
-
assert (res == [(1,)])
|
|
464
|
-
node.restart()
|
|
465
523
|
res = node.execute('select 2')
|
|
466
524
|
assert (res == [(2,)])
|
|
467
525
|
|
|
@@ -771,6 +829,8 @@ class TestTestgresCommon:
|
|
|
771
829
|
finally:
|
|
772
830
|
if node.is_started:
|
|
773
831
|
node.stop()
|
|
832
|
+
|
|
833
|
+
node.cleanup(release_resources=True)
|
|
774
834
|
return
|
|
775
835
|
|
|
776
836
|
def test_kill_backgroud_writer__ok(
|
|
@@ -1630,7 +1690,7 @@ class TestTestgresCommon:
|
|
|
1630
1690
|
|
|
1631
1691
|
nAttempt = 0
|
|
1632
1692
|
while True:
|
|
1633
|
-
if PostgresNodeUtils.
|
|
1693
|
+
if PostgresNodeUtils.detect_port_conflict(node_log_reader):
|
|
1634
1694
|
logging.info("Node port {} conflicted with another PostgreSQL instance.".format(
|
|
1635
1695
|
node.port
|
|
1636
1696
|
))
|
|
@@ -1726,12 +1786,9 @@ class TestTestgresCommon:
|
|
|
1726
1786
|
__class__.helper__skip_test_if_pg_version_is_not_ge(current_version, "9.6")
|
|
1727
1787
|
|
|
1728
1788
|
with __class__.helper__get_node(node_svc) as master:
|
|
1729
|
-
old_version = not __class__.helper__pg_version_ge(current_version, '9.6')
|
|
1730
|
-
|
|
1731
1789
|
master.init(allow_streaming=True).start()
|
|
1732
1790
|
|
|
1733
|
-
|
|
1734
|
-
master.append_conf('synchronous_commit = remote_apply')
|
|
1791
|
+
master.append_conf('synchronous_commit = remote_apply')
|
|
1735
1792
|
|
|
1736
1793
|
# create standby
|
|
1737
1794
|
with master.replicate() as standby1, master.replicate() as standby2:
|
|
@@ -1748,21 +1805,20 @@ class TestTestgresCommon:
|
|
|
1748
1805
|
|
|
1749
1806
|
# set synchronous_standby_names
|
|
1750
1807
|
master.set_synchronous_standbys(First(2, [standby1, standby2]))
|
|
1751
|
-
master.
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
assert (__class__.helper__rm_carriage_returns(res) == b'1000000\n')
|
|
1808
|
+
master.reload()
|
|
1809
|
+
|
|
1810
|
+
master.safe_psql('create table abc(a int)')
|
|
1811
|
+
|
|
1812
|
+
# Create a large transaction that will take some time to apply
|
|
1813
|
+
# on standby to check that it applies synchronously
|
|
1814
|
+
# (If set synchronous_commit to 'on' or other lower level then
|
|
1815
|
+
# standby most likely won't catchup so fast and test will fail)
|
|
1816
|
+
master.safe_psql(
|
|
1817
|
+
'insert into abc select generate_series(1, 1000000)',
|
|
1818
|
+
)
|
|
1819
|
+
res = standby1.safe_psql('select count(*) from abc')
|
|
1820
|
+
assert (__class__.helper__rm_carriage_returns(res) == b'1000000\n')
|
|
1821
|
+
return
|
|
1766
1822
|
|
|
1767
1823
|
def test_logical_replication(self, node_svc: PostgresNodeService):
|
|
1768
1824
|
assert isinstance(node_svc, PostgresNodeService)
|
|
@@ -82,6 +82,7 @@ class TestTestgresRemote:
|
|
|
82
82
|
assert isinstance(node_version, Version)
|
|
83
83
|
|
|
84
84
|
if node.version < Version("11"):
|
|
85
|
+
node.cleanup(release_resources=True)
|
|
85
86
|
pytest.skip("This test does not work on old PG10-.")
|
|
86
87
|
|
|
87
88
|
try:
|
|
@@ -152,6 +153,8 @@ class TestTestgresRemote:
|
|
|
152
153
|
assert expectedMsg2 in exc.error
|
|
153
154
|
continue
|
|
154
155
|
|
|
156
|
+
node.cleanup(release_resources=True)
|
|
157
|
+
|
|
155
158
|
if not errorIsDetected:
|
|
156
159
|
pytest.xfail("All the bad data are processed without errors!")
|
|
157
160
|
|
|
@@ -1,20 +0,0 @@
|
|
|
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)
|
|
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
|