Content-Length: 39170 | pFad | http://github.com/postgrespro/testgres/pull/255.patch
thub.com
From 99e645e8bcce52ac85d4dabdc6ae1e4bdceb4a17 Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Tue, 6 May 2025 15:52:11 +0300
Subject: [PATCH 01/13] [#247] PortManager__Generic uses lock-dirs for reserved
ports
---
testgres/consts.py | 4 +++
testgres/impl/port_manager__generic.py | 44 ++++++++++++++++++++++++--
2 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/testgres/consts.py b/testgres/consts.py
index 89c49ab7..d3589205 100644
--- a/testgres/consts.py
+++ b/testgres/consts.py
@@ -10,6 +10,10 @@
TMP_CACHE = 'tgsc_'
TMP_BACKUP = 'tgsb_'
+TMP_TESTGRES = "testgres"
+
+TMP_TESTGRES_PORTS = TMP_TESTGRES + "/ports"
+
# path to control file
XLOG_CONTROL_FILE = "global/pg_control"
diff --git a/testgres/impl/port_manager__generic.py b/testgres/impl/port_manager__generic.py
index a51af2bd..07cc2122 100755
--- a/testgres/impl/port_manager__generic.py
+++ b/testgres/impl/port_manager__generic.py
@@ -2,7 +2,9 @@
from ..port_manager import PortManager
from ..exceptions import PortForException
+from .. import consts
+import os
import threading
import random
import typing
@@ -15,6 +17,8 @@ class PortManager__Generic(PortManager):
_available_ports: typing.Set[int]
_reserved_ports: typing.Set[int]
+ _lock_dir: str
+
def __init__(self, os_ops: OsOperations):
assert os_ops is not None
assert isinstance(os_ops, OsOperations)
@@ -23,6 +27,12 @@ def __init__(self, os_ops: OsOperations):
self._available_ports: typing.Set[int] = set(range(1024, 65535))
self._reserved_ports: typing.Set[int] = set()
+ temp_dir = os_ops.get_tempdir()
+ assert type(temp_dir) == str # noqa: E721
+ self._lock_dir = os.path.join(temp_dir, consts.TMP_TESTGRES_PORTS)
+ assert type(self._lock_dir) == str # noqa: E721
+ os_ops.makedirs(self._lock_dir)
+
def reserve_port(self) -> int:
assert self._guard is not None
assert type(self._available_ports) == set # noqa: E721t
@@ -41,9 +51,23 @@ def reserve_port(self) -> int:
if not self._os_ops.is_port_free(port):
continue
- self._reserved_ports.add(port)
- self._available_ports.discard(port)
+ try:
+ lock_path = self.helper__make_lock_path(port)
+ self._os_ops.makedir(lock_path)
+ except: # noqa: 722
+ continue
+
+ assert self._os_ops.path_exists(lock_path)
+
+ try:
+ self._reserved_ports.add(port)
+ except: # noqa: 722
+ assert not (port in self._reserved_ports)
+ self._os_ops.rmdir(lock_path)
+ raise
+
assert port in self._reserved_ports
+ self._available_ports.discard(port)
assert not (port in self._available_ports)
return port
@@ -55,6 +79,8 @@ def release_port(self, number: int) -> None:
assert self._guard is not None
assert type(self._reserved_ports) == set # noqa: E721
+ lock_path = self.helper__make_lock_path(number)
+
with self._guard:
assert number in self._reserved_ports
assert not (number in self._available_ports)
@@ -62,3 +88,17 @@ def release_port(self, number: int) -> None:
self._reserved_ports.discard(number)
assert not (number in self._reserved_ports)
assert number in self._available_ports
+
+ assert isinstance(self._os_ops, OsOperations)
+ assert self._os_ops.path_exists(lock_path)
+ self._os_ops.rmdir(lock_path)
+
+ return
+
+ def helper__make_lock_path(self, port_number: int) -> str:
+ assert type(port_number) == int # noqa: E721
+ assert type(self._lock_dir) == str # noqa: E721
+
+ result = os.path.join(self._lock_dir, str(port_number) + ".lock")
+ assert type(result) == str # noqa: E721
+ return result
From c6f4b4df046aa37e3a72b5677a721f3ce6a60142 Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Wed, 7 May 2025 09:07:17 +0300
Subject: [PATCH 02/13] PortManager__Generic is refactored
- [FIX] A creation of self._log_dir is moved to reserve_port method
- Code normalization [copy&paste mistakes]
- New asserts are added
- New comments are added
---
testgres/impl/port_manager__generic.py | 26 +++++++++++++++++---------
1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/testgres/impl/port_manager__generic.py b/testgres/impl/port_manager__generic.py
index 07cc2122..cf60fa84 100755
--- a/testgres/impl/port_manager__generic.py
+++ b/testgres/impl/port_manager__generic.py
@@ -24,21 +24,28 @@ def __init__(self, os_ops: OsOperations):
assert isinstance(os_ops, OsOperations)
self._os_ops = os_ops
self._guard = threading.Lock()
- self._available_ports: typing.Set[int] = set(range(1024, 65535))
- self._reserved_ports: typing.Set[int] = set()
-
- temp_dir = os_ops.get_tempdir()
- assert type(temp_dir) == str # noqa: E721
- self._lock_dir = os.path.join(temp_dir, consts.TMP_TESTGRES_PORTS)
- assert type(self._lock_dir) == str # noqa: E721
- os_ops.makedirs(self._lock_dir)
+ self._available_ports = set(range(1024, 65535))
+ self._reserved_ports = set()
+ self._lock_dir = None
def reserve_port(self) -> int:
assert self._guard is not None
assert type(self._available_ports) == set # noqa: E721t
assert type(self._reserved_ports) == set # noqa: E721
+ assert isinstance(self._os_ops, OsOperations)
with self._guard:
+ if self._lock_dir is None:
+ temp_dir = self._os_ops.get_tempdir()
+ assert type(temp_dir) == str # noqa: E721
+ lock_dir = os.path.join(temp_dir, consts.TMP_TESTGRES_PORTS)
+ assert type(lock_dir) == str # noqa: E721
+ self._os_ops.makedirs(lock_dir)
+ self._lock_dir = lock_dir
+
+ assert self._lock_dir is not None
+ assert type(self._lock_dir) == str # noqa: E721
+
t = tuple(self._available_ports)
assert len(t) == len(self._available_ports)
sampled_ports = random.sample(t, min(len(t), 100))
@@ -53,7 +60,7 @@ def reserve_port(self) -> int:
try:
lock_path = self.helper__make_lock_path(port)
- self._os_ops.makedir(lock_path)
+ self._os_ops.makedir(lock_path) # raise
except: # noqa: 722
continue
@@ -97,6 +104,7 @@ def release_port(self, number: int) -> None:
def helper__make_lock_path(self, port_number: int) -> str:
assert type(port_number) == int # noqa: E721
+ # You have to call the reserve_port at first!
assert type(self._lock_dir) == str # noqa: E721
result = os.path.join(self._lock_dir, str(port_number) + ".lock")
From f085b70d52922b4f7ac3af9e064ae1296f725621 Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Wed, 7 May 2025 09:37:43 +0300
Subject: [PATCH 03/13] [#256] A used port range is [1024 ... 65535]
PortManager__Generic is updated.
---
testgres/impl/port_manager__generic.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/testgres/impl/port_manager__generic.py b/testgres/impl/port_manager__generic.py
index cf60fa84..fdf9e7a5 100755
--- a/testgres/impl/port_manager__generic.py
+++ b/testgres/impl/port_manager__generic.py
@@ -24,7 +24,7 @@ def __init__(self, os_ops: OsOperations):
assert isinstance(os_ops, OsOperations)
self._os_ops = os_ops
self._guard = threading.Lock()
- self._available_ports = set(range(1024, 65535))
+ self._available_ports = set(range(1024, 65536))
self._reserved_ports = set()
self._lock_dir = None
@@ -52,9 +52,13 @@ def reserve_port(self) -> int:
t = None
for port in sampled_ports:
+ assert type(port) == int # noqa: E721
assert not (port in self._reserved_ports)
assert port in self._available_ports
+ assert port >= 0
+ assert port <= 65535
+
if not self._os_ops.is_port_free(port):
continue
@@ -82,6 +86,8 @@ def reserve_port(self) -> int:
def release_port(self, number: int) -> None:
assert type(number) == int # noqa: E721
+ assert number >= 0
+ assert number <= 65535
assert self._guard is not None
assert type(self._reserved_ports) == set # noqa: E721
From c9b4bbf9a84b2f4f041e12afa8669f00287f9ec0 Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Wed, 7 May 2025 10:10:54 +0300
Subject: [PATCH 04/13] PortManager__Generic is refactored [consts, asserts]
---
testgres/impl/port_manager__generic.py | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/testgres/impl/port_manager__generic.py b/testgres/impl/port_manager__generic.py
index fdf9e7a5..3f312c13 100755
--- a/testgres/impl/port_manager__generic.py
+++ b/testgres/impl/port_manager__generic.py
@@ -11,6 +11,9 @@
class PortManager__Generic(PortManager):
+ C_MIN_PORT_NUMBER = 1024
+ C_MAX_PORT_NUMBER = 65535
+
_os_ops: OsOperations
_guard: object
# TODO: is there better to use bitmap fot _available_ports?
@@ -20,11 +23,20 @@ class PortManager__Generic(PortManager):
_lock_dir: str
def __init__(self, os_ops: OsOperations):
+ assert __class__.C_MIN_PORT_NUMBER <= __class__.C_MAX_PORT_NUMBER
+
assert os_ops is not None
assert isinstance(os_ops, OsOperations)
self._os_ops = os_ops
self._guard = threading.Lock()
- self._available_ports = set(range(1024, 65536))
+
+ self._available_ports = set(
+ range(__class__.C_MIN_PORT_NUMBER, __class__.C_MAX_PORT_NUMBER + 1)
+ )
+ assert len(self._available_ports) == (
+ (__class__.C_MAX_PORT_NUMBER - __class__.C_MIN_PORT_NUMBER) + 1
+ )
+
self._reserved_ports = set()
self._lock_dir = None
@@ -56,8 +68,8 @@ def reserve_port(self) -> int:
assert not (port in self._reserved_ports)
assert port in self._available_ports
- assert port >= 0
- assert port <= 65535
+ assert port >= __class__.C_MIN_PORT_NUMBER
+ assert port <= __class__.C_MAX_PORT_NUMBER
if not self._os_ops.is_port_free(port):
continue
@@ -86,8 +98,8 @@ def reserve_port(self) -> int:
def release_port(self, number: int) -> None:
assert type(number) == int # noqa: E721
- assert number >= 0
- assert number <= 65535
+ assert number >= __class__.C_MIN_PORT_NUMBER
+ assert number <= __class__.C_MAX_PORT_NUMBER
assert self._guard is not None
assert type(self._reserved_ports) == set # noqa: E721
From d15ecdba09aecb65e117f0aad8b03238ed363684 Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Thu, 29 May 2025 17:22:24 +0300
Subject: [PATCH 05/13] PortManager__Generic sends debug messages about its
operations.
This idea was taken from PgBouncer tests.
---
testgres/impl/port_manager__generic.py | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/testgres/impl/port_manager__generic.py b/testgres/impl/port_manager__generic.py
index 3f312c13..cbf4aa12 100755
--- a/testgres/impl/port_manager__generic.py
+++ b/testgres/impl/port_manager__generic.py
@@ -8,6 +8,7 @@
import threading
import random
import typing
+import logging
class PortManager__Generic(PortManager):
@@ -76,22 +77,29 @@ def reserve_port(self) -> int:
try:
lock_path = self.helper__make_lock_path(port)
+ __class__.helper__send_debug_msg("Attempting to create lock object {}.", lock_path)
self._os_ops.makedir(lock_path) # raise
except: # noqa: 722
+ __class__.helper__send_debug_msg("Lock object {} is not created.", lock_path)
continue
assert self._os_ops.path_exists(lock_path)
try:
+ __class__.helper__send_debug_msg("Lock object {} is created.", lock_path)
self._reserved_ports.add(port)
except: # noqa: 722
assert not (port in self._reserved_ports)
self._os_ops.rmdir(lock_path)
+ __class__.helper__send_debug_msg("Lock object {} was deleted during processing of failure.", lock_path)
raise
assert port in self._reserved_ports
self._available_ports.discard(port)
assert not (port in self._available_ports)
+
+ __class__.helper__send_debug_msg("Port {} is reserved.".format(port))
+
return port
raise PortForException("Can't select a port.")
@@ -117,9 +125,22 @@ def release_port(self, number: int) -> None:
assert isinstance(self._os_ops, OsOperations)
assert self._os_ops.path_exists(lock_path)
self._os_ops.rmdir(lock_path)
+ __class__.helper__send_debug_msg("Lock object {} was deleted.", lock_path)
+ __class__.helper__send_debug_msg("Port {} is released.", number)
return
+ @staticmethod
+ def helper__send_debug_msg(msg_template: str, *args) -> None:
+ assert msg_template is not None
+ assert str is not None
+ assert type(msg_template) == str # noqa: E721
+ assert type(args) == tuple # noqa: E721
+ assert msg_template != ""
+ s = "[port manager] "
+ s += msg_template.format(*args)
+ logging.debug(s)
+
def helper__make_lock_path(self, port_number: int) -> str:
assert type(port_number) == int # noqa: E721
# You have to call the reserve_port at first!
From 8e0869d498d7dd894e25f64dc65f26b4e939b1da Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Sat, 31 May 2025 23:25:31 +0300
Subject: [PATCH 06/13] [attention] OsOperations::create_lock_fs_obj is added
1) PortManager__Generic uses OsOperations::create_lock_fs_obj to create a lock object
2) utils.bound_ports is removed
- TestTestgresLocal.test_ports_management is deleted
- TestOsOpsCommon.test_create_lock_fs_obj is added
---
testgres/__init__.py | 7 +++---
testgres/impl/port_manager__generic.py | 33 +++++++++---------------
testgres/operations/local_ops.py | 22 ++++++++++++++++
testgres/operations/os_ops.py | 9 +++++++
testgres/operations/remote_ops.py | 32 +++++++++++++++++++++++
testgres/utils.py | 5 +---
tests/test_os_ops_common.py | 35 ++++++++++++++++++++++++++
tests/test_testgres_local.py | 35 --------------------------
8 files changed, 115 insertions(+), 63 deletions(-)
diff --git a/testgres/__init__.py b/testgres/__init__.py
index 339ae62e..959aaa41 100644
--- a/testgres/__init__.py
+++ b/testgres/__init__.py
@@ -39,7 +39,6 @@
from .utils import \
reserve_port, \
release_port, \
- bound_ports, \
get_bin_path, \
get_pg_config, \
get_pg_version
@@ -51,6 +50,7 @@
from .config import testgres_config
from .operations.os_ops import OsOperations, ConnectionParams
+from .operations.os_ops import OsLockObj
from .operations.local_ops import LocalOperations
from .operations.remote_ops import RemoteOperations
@@ -64,7 +64,8 @@
"XLogMethod", "IsolationLevel", "NodeStatus", "ProcessType", "DumpFormat",
"PostgresNode", "NodeApp",
"PortManager",
- "reserve_port", "release_port", "bound_ports", "get_bin_path", "get_pg_config", "get_pg_version",
+ "reserve_port", "release_port", "get_bin_path", "get_pg_config", "get_pg_version",
"First", "Any",
- "OsOperations", "LocalOperations", "RemoteOperations", "ConnectionParams"
+ "OsOperations", "LocalOperations", "RemoteOperations", "ConnectionParams",
+ "OsLockObj",
]
diff --git a/testgres/impl/port_manager__generic.py b/testgres/impl/port_manager__generic.py
index cbf4aa12..67949104 100755
--- a/testgres/impl/port_manager__generic.py
+++ b/testgres/impl/port_manager__generic.py
@@ -1,4 +1,5 @@
from ..operations.os_ops import OsOperations
+from ..operations.os_ops import OsLockObj
from ..port_manager import PortManager
from ..exceptions import PortForException
@@ -19,7 +20,7 @@ class PortManager__Generic(PortManager):
_guard: object
# TODO: is there better to use bitmap fot _available_ports?
_available_ports: typing.Set[int]
- _reserved_ports: typing.Set[int]
+ _reserved_ports: typing.Dict[int, OsLockObj]
_lock_dir: str
@@ -38,13 +39,13 @@ def __init__(self, os_ops: OsOperations):
(__class__.C_MAX_PORT_NUMBER - __class__.C_MIN_PORT_NUMBER) + 1
)
- self._reserved_ports = set()
+ self._reserved_ports = dict()
self._lock_dir = None
def reserve_port(self) -> int:
assert self._guard is not None
assert type(self._available_ports) == set # noqa: E721t
- assert type(self._reserved_ports) == set # noqa: E721
+ assert type(self._reserved_ports) == dict # noqa: E721
assert isinstance(self._os_ops, OsOperations)
with self._guard:
@@ -77,29 +78,24 @@ def reserve_port(self) -> int:
try:
lock_path = self.helper__make_lock_path(port)
- __class__.helper__send_debug_msg("Attempting to create lock object {}.", lock_path)
- self._os_ops.makedir(lock_path) # raise
+ lock_obj = self._os_ops.create_lock_fs_obj(lock_path) # raise
except: # noqa: 722
- __class__.helper__send_debug_msg("Lock object {} is not created.", lock_path)
continue
+ assert isinstance(lock_obj, OsLockObj)
assert self._os_ops.path_exists(lock_path)
try:
- __class__.helper__send_debug_msg("Lock object {} is created.", lock_path)
- self._reserved_ports.add(port)
+ self._reserved_ports[port] = lock_obj
except: # noqa: 722
assert not (port in self._reserved_ports)
- self._os_ops.rmdir(lock_path)
- __class__.helper__send_debug_msg("Lock object {} was deleted during processing of failure.", lock_path)
+ lock_obj.release()
raise
assert port in self._reserved_ports
self._available_ports.discard(port)
assert not (port in self._available_ports)
-
__class__.helper__send_debug_msg("Port {} is reserved.".format(port))
-
return port
raise PortForException("Can't select a port.")
@@ -110,22 +106,17 @@ def release_port(self, number: int) -> None:
assert number <= __class__.C_MAX_PORT_NUMBER
assert self._guard is not None
- assert type(self._reserved_ports) == set # noqa: E721
-
- lock_path = self.helper__make_lock_path(number)
+ assert type(self._reserved_ports) == dict # noqa: E721
with self._guard:
assert number in self._reserved_ports
assert not (number in self._available_ports)
self._available_ports.add(number)
- self._reserved_ports.discard(number)
+ lock_obj = self._reserved_ports.pop(number)
assert not (number in self._reserved_ports)
assert number in self._available_ports
-
- assert isinstance(self._os_ops, OsOperations)
- assert self._os_ops.path_exists(lock_path)
- self._os_ops.rmdir(lock_path)
- __class__.helper__send_debug_msg("Lock object {} was deleted.", lock_path)
+ assert isinstance(lock_obj, OsLockObj)
+ lock_obj.release()
__class__.helper__send_debug_msg("Port {} is released.", number)
return
diff --git a/testgres/operations/local_ops.py b/testgres/operations/local_ops.py
index ccf1ab82..67c75d01 100644
--- a/testgres/operations/local_ops.py
+++ b/testgres/operations/local_ops.py
@@ -15,6 +15,7 @@
from ..exceptions import ExecUtilException
from ..exceptions import InvalidOperationException
from .os_ops import ConnectionParams, OsOperations, get_default_encoding
+from .os_ops import OsLockObj
from .raise_error import RaiseError
from .helpers import Helpers
@@ -28,6 +29,23 @@
CMD_TIMEOUT_SEC = 60
+class LocalOsLockFsObj(OsLockObj):
+ m_path: str
+
+ def __init__(self, path: str):
+ assert type(path) == str # noqa: str
+ self.m_path = path
+ os.mkdir(path) # throw
+ assert os.path.exists(path)
+ self.m_path = path
+
+ def release(self) -> None:
+ assert type(self.m_path) == str # noqa: str
+ assert os.path.exists(self.m_path)
+ os.rmdir(self.m_path)
+ self.m_path = None
+
+
class LocalOperations(OsOperations):
sm_single_instance: OsOperations = None
sm_single_instance_guard = threading.Lock()
@@ -535,3 +553,7 @@ def get_tempdir(self) -> str:
assert type(r) == str # noqa: E721
assert os.path.exists(r)
return r
+
+ def create_lock_fs_obj(self, path: str) -> OsLockObj:
+ assert type(path) == str # noqa: E721
+ return LocalOsLockFsObj(path)
diff --git a/testgres/operations/os_ops.py b/testgres/operations/os_ops.py
index 45e4f71c..891c99b3 100644
--- a/testgres/operations/os_ops.py
+++ b/testgres/operations/os_ops.py
@@ -16,6 +16,11 @@ def get_default_encoding():
return locale.getencoding() or 'UTF-8'
+class OsLockObj:
+ def release(self) -> None:
+ raise NotImplementedError()
+
+
class OsOperations:
def __init__(self, username=None):
self.ssh_key = None
@@ -133,3 +138,7 @@ def is_port_free(self, number: int):
def get_tempdir(self) -> str:
raise NotImplementedError()
+
+ def create_lock_fs_obj(self, path: str) -> OsLockObj:
+ assert type(path) == str # noqa: E721
+ raise NotImplementedError()
diff --git a/testgres/operations/remote_ops.py b/testgres/operations/remote_ops.py
index a478b453..2478ab08 100644
--- a/testgres/operations/remote_ops.py
+++ b/testgres/operations/remote_ops.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
import getpass
import os
import platform
@@ -10,6 +12,7 @@
from ..exceptions import ExecUtilException
from ..exceptions import InvalidOperationException
from .os_ops import OsOperations, ConnectionParams, get_default_encoding
+from .os_ops import OsLockObj
from .raise_error import RaiseError
from .helpers import Helpers
@@ -40,6 +43,31 @@ def cmdline(self):
return cmdline.split()
+class RemoteOsLockFsObj(OsLockObj):
+ m_os_ops: RemoteOperations
+ m_path: str
+
+ def __init__(self, os_ops: RemoteOperations, path: str):
+ assert isinstance(os_ops, RemoteOperations)
+ assert type(path) == str # noqa: str
+
+ os_ops.makedir(path) # throw
+ assert os_ops.path_exists(path)
+
+ self.m_os_ops = os_ops
+ self.m_path = path
+
+ def release(self) -> None:
+ assert type(self.m_path) == str # noqa: str
+ assert isinstance(self.m_os_ops, RemoteOperations)
+ assert self.m_os_ops.path_exists(self.m_path)
+
+ self.m_os_ops.rmdir(self.m_path) # throw
+
+ self.m_path = None
+ self.m_os_ops = None
+
+
class RemoteOperations(OsOperations):
def __init__(self, conn_params: ConnectionParams):
if not platform.system().lower() == "linux":
@@ -687,6 +715,10 @@ def get_tempdir(self) -> str:
assert type(temp_dir) == str # noqa: E721
return temp_dir
+ def create_lock_fs_obj(self, path: str) -> OsLockObj:
+ assert type(path) == str # noqa: E721
+ return RemoteOsLockFsObj(self, path)
+
@staticmethod
def _is_port_free__process_0(error: str) -> bool:
assert type(error) == str # noqa: E721
diff --git a/testgres/utils.py b/testgres/utils.py
index d231eec3..d8086655 100644
--- a/testgres/utils.py
+++ b/testgres/utils.py
@@ -30,9 +30,6 @@
#
_old_port_manager = PortManager__Generic(LocalOperations.get_single_instance())
-# ports used by nodes
-bound_ports = _old_port_manager._reserved_ports
-
# re-export version type
class PgVer(Version):
@@ -46,7 +43,7 @@ def __init__(self, version: str) -> None:
def internal__reserve_port():
"""
- Generate a new port and add it to 'bound_ports'.
+ Reserve a port.
"""
return _old_port_manager.reserve_port()
diff --git a/tests/test_os_ops_common.py b/tests/test_os_ops_common.py
index 5ae3a61f..c999f44e 100644
--- a/tests/test_os_ops_common.py
+++ b/tests/test_os_ops_common.py
@@ -17,6 +17,7 @@
from testgres import InvalidOperationException
from testgres import ExecUtilException
+from testgres.operations.os_ops import OsLockObj
from concurrent.futures import ThreadPoolExecutor
from concurrent.futures import Future as ThreadFuture
@@ -1113,3 +1114,37 @@ class tadWorkerData:
logging.info("Test is finished! Total error count is {}.".format(nErrors))
return
+
+ def test_create_lock_fs_obj(self, os_ops: OsOperations):
+ assert isinstance(os_ops, OsOperations)
+
+ tmp = os_ops.mkdtemp()
+ assert type(tmp) == str # noqa: E721
+ assert os_ops.path_exists(tmp)
+ logging.info("tmp dir is [{}]".format(tmp))
+
+ p1 = os.path.join(tmp, "a.lock")
+ obj1 = os_ops.create_lock_fs_obj(p1)
+ assert obj1 is not None
+ assert isinstance(obj1, OsLockObj)
+ assert os_ops.path_exists(tmp)
+ assert os_ops.path_exists(p1)
+
+ while True:
+ try:
+ os_ops.create_lock_fs_obj(p1)
+ except Exception as e:
+ logging.info("OK. We got the error ({}): {}".format(type(e).__name__, e))
+ break
+ raise Exception("We wait the exception!")
+
+ assert isinstance(obj1, OsLockObj)
+ assert os_ops.path_exists(tmp)
+ assert os_ops.path_exists(p1)
+
+ obj1.release()
+ assert not os_ops.path_exists(p1)
+
+ assert os_ops.path_exists(tmp)
+ os_ops.rmdir(tmp)
+ assert not os_ops.path_exists(tmp)
diff --git a/tests/test_testgres_local.py b/tests/test_testgres_local.py
index 63e5f37e..d8765f86 100644
--- a/tests/test_testgres_local.py
+++ b/tests/test_testgres_local.py
@@ -19,7 +19,6 @@
from testgres import get_pg_version
# NOTE: those are ugly imports
-from testgres.utils import bound_ports
from testgres.utils import PgVer
from testgres.node import ProcessProxy
@@ -90,40 +89,6 @@ def test_pg_config(self):
b = get_pg_config()
assert (id(a) != id(b))
- def test_ports_management(self):
- assert bound_ports is not None
- assert type(bound_ports) == set # noqa: E721
-
- if len(bound_ports) != 0:
- logging.warning("bound_ports is not empty: {0}".format(bound_ports))
-
- stage0__bound_ports = bound_ports.copy()
-
- with get_new_node() as node:
- assert bound_ports is not None
- assert type(bound_ports) == set # noqa: E721
-
- assert node.port is not None
- assert type(node.port) == int # noqa: E721
-
- logging.info("node port is {0}".format(node.port))
-
- assert node.port in bound_ports
- assert node.port not in stage0__bound_ports
-
- assert stage0__bound_ports <= bound_ports
- assert len(stage0__bound_ports) + 1 == len(bound_ports)
-
- stage1__bound_ports = stage0__bound_ports.copy()
- stage1__bound_ports.add(node.port)
-
- assert stage1__bound_ports == bound_ports
-
- # check that port has been freed successfully
- assert bound_ports is not None
- assert type(bound_ports) == set # noqa: E721
- assert bound_ports == stage0__bound_ports
-
def test_child_process_dies(self):
# test for FileNotFound exception during child_processes() function
cmd = ["timeout", "60"] if os.name == 'nt' else ["sleep", "60"]
From 82b46b3594237c991cbb5dd9a8c061f46afd64cb Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Sun, 1 Jun 2025 13:14:40 +0300
Subject: [PATCH 07/13] Code style is fixed
---
testgres/operations/local_ops.py | 14 +++++++-------
testgres/operations/remote_ops.py | 20 ++++++++++----------
2 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/testgres/operations/local_ops.py b/testgres/operations/local_ops.py
index 67c75d01..e7945078 100644
--- a/testgres/operations/local_ops.py
+++ b/testgres/operations/local_ops.py
@@ -30,20 +30,20 @@
class LocalOsLockFsObj(OsLockObj):
- m_path: str
+ _path: str
def __init__(self, path: str):
assert type(path) == str # noqa: str
- self.m_path = path
+ self._path = path
os.mkdir(path) # throw
assert os.path.exists(path)
- self.m_path = path
+ self._path = path
def release(self) -> None:
- assert type(self.m_path) == str # noqa: str
- assert os.path.exists(self.m_path)
- os.rmdir(self.m_path)
- self.m_path = None
+ assert type(self._path) == str # noqa: str
+ assert os.path.exists(self._path)
+ os.rmdir(self._path)
+ self._path = None
class LocalOperations(OsOperations):
diff --git a/testgres/operations/remote_ops.py b/testgres/operations/remote_ops.py
index 2478ab08..9ecfed51 100644
--- a/testgres/operations/remote_ops.py
+++ b/testgres/operations/remote_ops.py
@@ -44,8 +44,8 @@ def cmdline(self):
class RemoteOsLockFsObj(OsLockObj):
- m_os_ops: RemoteOperations
- m_path: str
+ _os_ops: RemoteOperations
+ _path: str
def __init__(self, os_ops: RemoteOperations, path: str):
assert isinstance(os_ops, RemoteOperations)
@@ -54,18 +54,18 @@ def __init__(self, os_ops: RemoteOperations, path: str):
os_ops.makedir(path) # throw
assert os_ops.path_exists(path)
- self.m_os_ops = os_ops
- self.m_path = path
+ self._os_ops = os_ops
+ self._path = path
def release(self) -> None:
- assert type(self.m_path) == str # noqa: str
- assert isinstance(self.m_os_ops, RemoteOperations)
- assert self.m_os_ops.path_exists(self.m_path)
+ assert type(self._path) == str # noqa: str
+ assert isinstance(self._os_ops, RemoteOperations)
+ assert self._os_ops.path_exists(self._path)
- self.m_os_ops.rmdir(self.m_path) # throw
+ self._os_ops.rmdir(self._path) # throw
- self.m_path = None
- self.m_os_ops = None
+ self._path = None
+ self._os_ops = None
class RemoteOperations(OsOperations):
From 597f699b1fa236261a4a0df5ac30bc78607b71a6 Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Tue, 24 Jun 2025 10:53:41 +0300
Subject: [PATCH 08/13] PortManager__Generic is synchronized with master
- _C_MIN_PORT_NUMBER
- _C_MAX_PORT_NUMBER
---
testgres/impl/port_manager__generic.py | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/testgres/impl/port_manager__generic.py b/testgres/impl/port_manager__generic.py
index 67949104..f1b27925 100755
--- a/testgres/impl/port_manager__generic.py
+++ b/testgres/impl/port_manager__generic.py
@@ -13,8 +13,8 @@
class PortManager__Generic(PortManager):
- C_MIN_PORT_NUMBER = 1024
- C_MAX_PORT_NUMBER = 65535
+ _C_MIN_PORT_NUMBER = 1024
+ _C_MAX_PORT_NUMBER = 65535
_os_ops: OsOperations
_guard: object
@@ -25,7 +25,7 @@ class PortManager__Generic(PortManager):
_lock_dir: str
def __init__(self, os_ops: OsOperations):
- assert __class__.C_MIN_PORT_NUMBER <= __class__.C_MAX_PORT_NUMBER
+ assert __class__._C_MIN_PORT_NUMBER <= __class__._C_MAX_PORT_NUMBER
assert os_ops is not None
assert isinstance(os_ops, OsOperations)
@@ -33,10 +33,10 @@ def __init__(self, os_ops: OsOperations):
self._guard = threading.Lock()
self._available_ports = set(
- range(__class__.C_MIN_PORT_NUMBER, __class__.C_MAX_PORT_NUMBER + 1)
+ range(__class__._C_MIN_PORT_NUMBER, __class__._C_MAX_PORT_NUMBER + 1)
)
assert len(self._available_ports) == (
- (__class__.C_MAX_PORT_NUMBER - __class__.C_MIN_PORT_NUMBER) + 1
+ (__class__._C_MAX_PORT_NUMBER - __class__._C_MIN_PORT_NUMBER) + 1
)
self._reserved_ports = dict()
@@ -70,8 +70,8 @@ def reserve_port(self) -> int:
assert not (port in self._reserved_ports)
assert port in self._available_ports
- assert port >= __class__.C_MIN_PORT_NUMBER
- assert port <= __class__.C_MAX_PORT_NUMBER
+ assert port >= __class__._C_MIN_PORT_NUMBER
+ assert port <= __class__._C_MAX_PORT_NUMBER
if not self._os_ops.is_port_free(port):
continue
@@ -102,8 +102,8 @@ def reserve_port(self) -> int:
def release_port(self, number: int) -> None:
assert type(number) == int # noqa: E721
- assert number >= __class__.C_MIN_PORT_NUMBER
- assert number <= __class__.C_MAX_PORT_NUMBER
+ assert number >= __class__._C_MIN_PORT_NUMBER
+ assert number <= __class__._C_MAX_PORT_NUMBER
assert self._guard is not None
assert type(self._reserved_ports) == dict # noqa: E721
From b34837ef69dd638a1e845b737fa28733e200f6e0 Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Tue, 24 Jun 2025 10:56:00 +0300
Subject: [PATCH 09/13] [FIX] PortManager__Generic::release_port sends a debug
message under guard
---
testgres/impl/port_manager__generic.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/testgres/impl/port_manager__generic.py b/testgres/impl/port_manager__generic.py
index f1b27925..af67559b 100755
--- a/testgres/impl/port_manager__generic.py
+++ b/testgres/impl/port_manager__generic.py
@@ -117,8 +117,7 @@ def release_port(self, number: int) -> None:
assert number in self._available_ports
assert isinstance(lock_obj, OsLockObj)
lock_obj.release()
-
- __class__.helper__send_debug_msg("Port {} is released.", number)
+ __class__.helper__send_debug_msg("Port {} is released.", number)
return
@staticmethod
From 0648926b081702c7f86b1730559b50aa9e7579f6 Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Tue, 24 Jun 2025 11:02:35 +0300
Subject: [PATCH 10/13] PortManager__Generic::reserve_port is updated
(reordered)
---
testgres/impl/port_manager__generic.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/testgres/impl/port_manager__generic.py b/testgres/impl/port_manager__generic.py
index af67559b..05ccc02d 100755
--- a/testgres/impl/port_manager__generic.py
+++ b/testgres/impl/port_manager__generic.py
@@ -92,8 +92,8 @@ def reserve_port(self) -> int:
lock_obj.release()
raise
- assert port in self._reserved_ports
self._available_ports.discard(port)
+ assert port in self._reserved_ports
assert not (port in self._available_ports)
__class__.helper__send_debug_msg("Port {} is reserved.".format(port))
return port
From 8c5e34014842e20eaaf44d0da525b3d1bec2fa9f Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Tue, 24 Jun 2025 12:15:44 +0300
Subject: [PATCH 11/13] PortManager__Generic::helper__send_debug_msg is
corrected (assert)
---
testgres/impl/port_manager__generic.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/testgres/impl/port_manager__generic.py b/testgres/impl/port_manager__generic.py
index 05ccc02d..ad0b3a91 100755
--- a/testgres/impl/port_manager__generic.py
+++ b/testgres/impl/port_manager__generic.py
@@ -123,7 +123,7 @@ def release_port(self, number: int) -> None:
@staticmethod
def helper__send_debug_msg(msg_template: str, *args) -> None:
assert msg_template is not None
- assert str is not None
+ assert args is not None
assert type(msg_template) == str # noqa: E721
assert type(args) == tuple # noqa: E721
assert msg_template != ""
From ea25215d638fcc51c77ddebf77956af5bbbc8284 Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Tue, 24 Jun 2025 12:18:40 +0300
Subject: [PATCH 12/13] PortManager__Generic::reserve_port is updated (comment)
---
testgres/impl/port_manager__generic.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/testgres/impl/port_manager__generic.py b/testgres/impl/port_manager__generic.py
index ad0b3a91..33254b03 100755
--- a/testgres/impl/port_manager__generic.py
+++ b/testgres/impl/port_manager__generic.py
@@ -44,7 +44,7 @@ def __init__(self, os_ops: OsOperations):
def reserve_port(self) -> int:
assert self._guard is not None
- assert type(self._available_ports) == set # noqa: E721t
+ assert type(self._available_ports) == set # noqa: E721
assert type(self._reserved_ports) == dict # noqa: E721
assert isinstance(self._os_ops, OsOperations)
From aa677d28bdbd40919abcf30576354f8271626208 Mon Sep 17 00:00:00 2001
From: "d.kovalenko"
Date: Tue, 24 Jun 2025 12:28:00 +0300
Subject: [PATCH 13/13] PortManager__Generic::__init__ is updated
---
testgres/impl/port_manager__generic.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/testgres/impl/port_manager__generic.py b/testgres/impl/port_manager__generic.py
index 33254b03..79c41b2f 100755
--- a/testgres/impl/port_manager__generic.py
+++ b/testgres/impl/port_manager__generic.py
@@ -38,9 +38,9 @@ def __init__(self, os_ops: OsOperations):
assert len(self._available_ports) == (
(__class__._C_MAX_PORT_NUMBER - __class__._C_MIN_PORT_NUMBER) + 1
)
-
self._reserved_ports = dict()
self._lock_dir = None
+ return
def reserve_port(self) -> int:
assert self._guard is not None
--- a PPN by Garber Painting Akron. With Image Size Reduction included!Fetched URL: http://github.com/postgrespro/testgres/pull/255.patch
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy