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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy