Skip to content

PortManager #234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
09dab31
PostgresNode refactoring [PostgresNodePortManager and RO-properties]
dmitry-lipetsk Apr 3, 2025
ef095d3
[FIX] clone_with_new_name_and_base_dir did not respect port_manager
dmitry-lipetsk Apr 4, 2025
0f842fd
PostgresNodePortManager__ThisHost is defined (was: PostgresNodePortMa…
dmitry-lipetsk Apr 4, 2025
e1e609e
PostgresNodePortManager__Generic is added
dmitry-lipetsk Apr 4, 2025
285e5b7
PostgresNodePortManager is added in public API
dmitry-lipetsk Apr 4, 2025
a974866
Test structures were refactored (local, local2, remote)
dmitry-lipetsk Apr 4, 2025
110947d
CI files are updated
dmitry-lipetsk Apr 4, 2025
4f49dde
TestTestgresCommon.test_pgbench is added
dmitry-lipetsk Apr 4, 2025
4fbf51d
PostgresNodePortManager is updated [error messages]
dmitry-lipetsk Apr 4, 2025
17c73cb
PostgresNodePortManager(+company) was moved in own file - port_manage…
dmitry-lipetsk Apr 4, 2025
b1cee19
PortManager was deleted [amen]
dmitry-lipetsk Apr 4, 2025
c5ad907
PostgresNodePortManager was renamed with PortManager
dmitry-lipetsk Apr 4, 2025
0967057
TestTestgresCommon.test_unix_sockets is added
dmitry-lipetsk Apr 4, 2025
1d450b2
TestTestgresCommon.test_the_same_port is added
dmitry-lipetsk Apr 4, 2025
4a38b35
[TestTestgresCommon] New tests are added
dmitry-lipetsk Apr 4, 2025
322fb23
RemoteOperations::is_port_free is updated
dmitry-lipetsk Apr 4, 2025
94da63e
Tests for OsOps::is_port_free are added
dmitry-lipetsk Apr 4, 2025
88f9b73
TestTestgresCommon is corrected [python problems]
dmitry-lipetsk Apr 4, 2025
d9558ce
The call of RaiseError.CommandExecutionError is fixed [message, not m…
dmitry-lipetsk Apr 4, 2025
0da4c21
[CI] ubuntu 24.04 does not have nc
dmitry-lipetsk Apr 4, 2025
0058508
RemoteOperations is update [private method names]
dmitry-lipetsk Apr 5, 2025
8f3a566
test_is_port_free__true is updated
dmitry-lipetsk Apr 5, 2025
d8ebdb7
RemoteOperations::is_port_free is updated (comments)
dmitry-lipetsk Apr 5, 2025
30e472c
setup.py is updated [testgres.helpers was deleted]
dmitry-lipetsk Apr 5, 2025
c94bbb5
Comment in node.py is updated
dmitry-lipetsk Apr 5, 2025
04f88c7
PostgresNode::_node was deleted [use self._os_ops.host]
dmitry-lipetsk Apr 5, 2025
0a3442a
PostgresNode::start is corrected [error message]
dmitry-lipetsk Apr 5, 2025
30124f3
Merge branch 'master' into D20250403_001--port_manager
dmitry-lipetsk Apr 5, 2025
13e71d8
[FIX] PostgresNode.__init__ must not test "os_ops.host" attribute.
dmitry-lipetsk Apr 5, 2025
9e14f4a
PostgresNode.free_port always set a port to None
dmitry-lipetsk Apr 6, 2025
739ef61
[FIX] flake8 (noqa: E721)
dmitry-lipetsk Apr 6, 2025
696cc1e
PortManager__Generic is refactored
dmitry-lipetsk Apr 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[TestTestgresCommon] New tests are added
- test_port_rereserve_during_node_start
- test_port_conflict
  • Loading branch information
dmitry-lipetsk committed Apr 4, 2025
commit 4a38b35dda82360a59e6c73f7614998810bcf248
167 changes: 165 additions & 2 deletions tests/test_testgres_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from ..testgres import NodeStatus
from ..testgres import IsolationLevel

import testgres

# New name prevents to collect test-functions in TestgresException and fixes
# the problem with pytest warning.
from ..testgres import TestgresException as testgres_TestgresException
Expand All @@ -39,6 +41,7 @@
import os
import re
import subprocess
import typing


@contextmanager
Expand Down Expand Up @@ -1169,17 +1172,177 @@ def test_the_same_port(self, node_svc: PostgresNodeService):
r = node.safe_psql("SELECT 3;")
assert (__class__.helper__rm_carriage_returns(r) == b'3\n')

class tagPortManagerProxy(PortManager):
m_PrevPortManager: PortManager

m_DummyPortNumber: int
m_DummyPortMaxUsage: int

m_DummyPortCurrentUsage: int
m_DummyPortTotalUsage: int

def __init__(self, prevPortManager: PortManager, dummyPortNumber: int, dummyPortMaxUsage: int):
assert isinstance(prevPortManager, PortManager)
assert type(dummyPortNumber) == int # noqa: E721
assert type(dummyPortMaxUsage) == int # noqa: E721
assert dummyPortNumber >= 0
assert dummyPortMaxUsage >= 0

super().__init__()

self.m_PrevPortManager = prevPortManager

self.m_DummyPortNumber = dummyPortNumber
self.m_DummyPortMaxUsage = dummyPortMaxUsage

self.m_DummyPortCurrentUsage = 0
self.m_DummyPortTotalUsage = 0

def __enter__(self):
return self

def __exit__(self, type, value, traceback):
assert self.m_DummyPortCurrentUsage == 0

assert self.m_PrevPortManager is not None

def reserve_port(self) -> int:
assert type(self.m_DummyPortMaxUsage) == int # noqa: E721
assert type(self.m_DummyPortTotalUsage) == int # noqa: E721
assert type(self.m_DummyPortCurrentUsage) == int # noqa: E721
assert self.m_DummyPortTotalUsage >= 0
assert self.m_DummyPortCurrentUsage >= 0

assert self.m_DummyPortTotalUsage <= self.m_DummyPortMaxUsage
assert self.m_DummyPortCurrentUsage <= self.m_DummyPortTotalUsage

assert self.m_PrevPortManager is not None
assert isinstance(self.m_PrevPortManager, PortManager)

if self.m_DummyPortTotalUsage == self.m_DummyPortMaxUsage:
return self.m_PrevPortManager.reserve_port()

self.m_DummyPortTotalUsage += 1
self.m_DummyPortCurrentUsage += 1
return self.m_DummyPortNumber

def release_port(self, dummyPortNumber: int):
assert type(dummyPortNumber) == int # noqa: E721

assert type(self.m_DummyPortMaxUsage) == int # noqa: E721
assert type(self.m_DummyPortTotalUsage) == int # noqa: E721
assert type(self.m_DummyPortCurrentUsage) == int # noqa: E721
assert self.m_DummyPortTotalUsage >= 0
assert self.m_DummyPortCurrentUsage >= 0

assert self.m_DummyPortTotalUsage <= self.m_DummyPortMaxUsage
assert self.m_DummyPortCurrentUsage <= self.m_DummyPortTotalUsage

assert self.m_PrevPortManager is not None
assert isinstance(self.m_PrevPortManager, PortManager)

if self.m_DummyPortCurrentUsage > 0 and dummyPortNumber == self.m_DummyPortNumber:
assert self.m_DummyPortTotalUsage > 0
self.m_DummyPortCurrentUsage -= 1
return

return self.m_PrevPortManager.release_port(dummyPortNumber)

def test_port_rereserve_during_node_start(self, node_svc: PostgresNodeService):
assert type(node_svc) == PostgresNodeService # noqa: E721
assert testgres.PostgresNode._C_MAX_START_ATEMPTS == 5

C_COUNT_OF_BAD_PORT_USAGE = 3

with __class__.helper__get_node(node_svc) as node1:
node1.init().start()
assert node1._should_free_port
assert type(node1.port) == int # noqa: E721
node1_port_copy = node1.port
assert __class__.helper__rm_carriage_returns(node1.safe_psql("SELECT 1;")) == b'1\n'

with __class__.tagPortManagerProxy(node_svc.port_manager, node1.port, C_COUNT_OF_BAD_PORT_USAGE) as proxy:
assert proxy.m_DummyPortNumber == node1.port
with __class__.helper__get_node(node_svc, port_manager=proxy) as node2:
assert node2._should_free_port
assert node2.port == node1.port

node2.init().start()

assert node2.port != node1.port
assert node2._should_free_port
assert proxy.m_DummyPortCurrentUsage == 0
assert proxy.m_DummyPortTotalUsage == C_COUNT_OF_BAD_PORT_USAGE
assert node2.is_started
r = node2.safe_psql("SELECT 2;")
assert __class__.helper__rm_carriage_returns(r) == b'2\n'

# node1 is still working
assert node1.port == node1_port_copy
assert node1._should_free_port
r = node1.safe_psql("SELECT 3;")
assert __class__.helper__rm_carriage_returns(r) == b'3\n'

def test_port_conflict(self, node_svc: PostgresNodeService):
assert type(node_svc) == PostgresNodeService # noqa: E721
assert testgres.PostgresNode._C_MAX_START_ATEMPTS > 1

C_COUNT_OF_BAD_PORT_USAGE = testgres.PostgresNode._C_MAX_START_ATEMPTS

with __class__.helper__get_node(node_svc) as node1:
node1.init().start()
assert node1._should_free_port
assert type(node1.port) == int # noqa: E721
node1_port_copy = node1.port
assert __class__.helper__rm_carriage_returns(node1.safe_psql("SELECT 1;")) == b'1\n'

with __class__.tagPortManagerProxy(node_svc.port_manager, node1.port, C_COUNT_OF_BAD_PORT_USAGE) as proxy:
assert proxy.m_DummyPortNumber == node1.port
with __class__.helper__get_node(node_svc, port_manager=proxy) as node2:
assert node2._should_free_port
assert node2.port == node1.port

with pytest.raises(
expected_exception=StartNodeException,
match=re.escape("Cannot start node after multiple attempts.")
):
node2.init().start()

assert node2.port == node1.port
assert node2._should_free_port
assert proxy.m_DummyPortCurrentUsage == 1
assert proxy.m_DummyPortTotalUsage == C_COUNT_OF_BAD_PORT_USAGE
assert not node2.is_started

# node2 must release our dummyPort (node1.port)
assert (proxy.m_DummyPortCurrentUsage == 0)

# node1 is still working
assert node1.port == node1_port_copy
assert node1._should_free_port
r = node1.safe_psql("SELECT 3;")
assert __class__.helper__rm_carriage_returns(r) == b'3\n'

@staticmethod
def helper__get_node(node_svc: PostgresNodeService, name=None, port=None):
def helper__get_node(
node_svc: PostgresNodeService,
name: typing.Optional[str] = None,
port: typing.Optional[int] = None,
port_manager: typing.Optional[PortManager] = None
) -> PostgresNode:
assert isinstance(node_svc, PostgresNodeService)
assert isinstance(node_svc.os_ops, OsOperations)
assert isinstance(node_svc.port_manager, PortManager)

if port_manager is None:
port_manager = node_svc.port_manager

return PostgresNode(
name,
port=port,
conn_params=None,
os_ops=node_svc.os_ops,
port_manager=node_svc.port_manager if port is None else None
port_manager=port_manager if port is None else None
)

@staticmethod
Expand Down