Skip to content

Commit 5db1a8f

Browse files
PostgresNode::slow_start and tests are updated (#313)
PostgresNode::slow_start stops a node if it fails to wait for finish of initialization. Client expects to have fully started node. TestTestgresLocal::test_port_conflict is updated. Checks of node statuses are added. TestTestgresCommon::test_double_start is updated. Checks of node statuses are added. TestTestgresCommon::test_uninitialized_start is updated. Checks of node statuses are added. TestTestgresCommon::test_restart is updated. Checks of node statuses are added. TestTestgresCommon::test_the_same_port is updated. Normalization. Checks of node statuses are added. TestTestgresCommon::test_node_app__make_empty_with_explicit_port is rewritten. It does 5 attempts to start a node with a manually defined port number.
1 parent 7a5dabd commit 5db1a8f

3 files changed

Lines changed: 121 additions & 40 deletions

File tree

src/node.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -975,19 +975,31 @@ def slow_start(self, replica=False, dbname='template1', username=None, max_attem
975975

976976
self.start(exec_env=exec_env)
977977

978-
if replica:
979-
query = 'SELECT pg_is_in_recovery()'
980-
else:
981-
query = 'SELECT not pg_is_in_recovery()'
982-
# Call poll_query_until until the expected value is returned
983-
self.poll_query_until(query=query,
984-
dbname=dbname,
985-
username=username or self.os_ops.username,
986-
suppress={InternalError,
987-
QueryException,
988-
ProgrammingError,
989-
OperationalError},
990-
max_attempts=max_attempts)
978+
try:
979+
if replica:
980+
query = 'SELECT pg_is_in_recovery()'
981+
else:
982+
query = 'SELECT not pg_is_in_recovery()'
983+
984+
# Call poll_query_until until the expected value is returned
985+
suppressed_exceptions = {
986+
InternalError,
987+
QueryException,
988+
ProgrammingError,
989+
OperationalError
990+
}
991+
992+
self.poll_query_until(
993+
query=query,
994+
dbname=dbname,
995+
username=username or self.os_ops.username,
996+
suppress=suppressed_exceptions,
997+
max_attempts=max_attempts,
998+
)
999+
except: # noqa: E722
1000+
self.stop()
1001+
raise
1002+
return
9911003

9921004
def start(self, params=[], wait=True, exec_env=None):
9931005
"""

tests/test_testgres_common.py

Lines changed: 91 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,10 @@ def test_double_start(self, node_svc: PostgresNodeService):
210210
with __class__.helper__get_node(node_svc) as node:
211211
node.init()
212212
assert not node.is_started
213+
assert node.status() == NodeStatus.Stopped
213214
node.start()
214215
assert node.is_started
216+
assert node.status() == NodeStatus.Running
215217

216218
with pytest.raises(expected_exception=StartNodeException) as x:
217219
# can't start node more than once
@@ -226,6 +228,7 @@ def test_double_start(self, node_svc: PostgresNodeService):
226228
assert x.value.message.startswith(x.value.description)
227229

228230
assert node.is_started
231+
assert node.status() == NodeStatus.Running
229232

230233
return
231234

@@ -272,9 +275,14 @@ def test_uninitialized_start(self, node_svc: PostgresNodeService):
272275

273276
with __class__.helper__get_node(node_svc) as node:
274277
# node is not initialized yet
278+
assert node.status() == NodeStatus.Uninitialized
279+
275280
with pytest.raises(expected_exception=StartNodeException):
276281
node.start()
277282

283+
assert node.status() == NodeStatus.Uninitialized
284+
return
285+
278286
def test_restart(self, node_svc: PostgresNodeService):
279287
assert isinstance(node_svc, PostgresNodeService)
280288

@@ -288,11 +296,16 @@ def test_restart(self, node_svc: PostgresNodeService):
288296
res = node.execute('select 2')
289297
assert (res == [(2,)])
290298

299+
assert node.status() == NodeStatus.Running
300+
291301
# restart, fail
292302
with pytest.raises(expected_exception=StartNodeException):
293303
node.append_conf('pg_hba.conf', 'DUMMY')
294304
node.restart()
295305

306+
assert node.status() == NodeStatus.Stopped
307+
return
308+
296309
def test_double_stop(self, node_svc: PostgresNodeService):
297310
assert isinstance(node_svc, PostgresNodeService)
298311

@@ -1618,13 +1631,18 @@ def test_the_same_port(self, node_svc: PostgresNodeService):
16181631
with __class__.helper__get_node(node_svc, port=node.port) as node2:
16191632
assert (type(node2.port) == int) # noqa: E721
16201633
assert (node2.port == node.port)
1621-
assert not (node2._should_free_port)
1634+
assert (not node2._should_free_port)
1635+
assert (node2.status() == NodeStatus.Uninitialized)
1636+
1637+
node2.init()
16221638

16231639
with pytest.raises(
16241640
expected_exception=StartNodeException,
16251641
match=re.escape("Cannot start node")
16261642
):
1627-
node2.init().start()
1643+
node2.start()
1644+
1645+
assert (node2.status() == NodeStatus.Stopped)
16281646

16291647
# node is still working
16301648
assert (node.port == node_port_copy)
@@ -2124,6 +2142,8 @@ def test_node_app__make_empty_with_explicit_port(self, node_svc: PostgresNodeSer
21242142
assert node_svc.port_manager is not None
21252143
assert isinstance(node_svc.port_manager, PortManager)
21262144

2145+
C_MAX_ATTEMPTS = 5
2146+
21272147
tmp_dir = node_svc.os_ops.mkdtemp()
21282148
assert tmp_dir is not None
21292149
assert type(tmp_dir) == str # noqa: E721
@@ -2141,37 +2161,83 @@ def test_node_app__make_empty_with_explicit_port(self, node_svc: PostgresNodeSer
21412161
assert type(node_app.nodes_to_cleanup) == list # noqa: E721
21422162
assert len(node_app.nodes_to_cleanup) == 0
21432163

2144-
port = node_app.port_manager.reserve_port()
2145-
assert type(port) == int # noqa: E721
2146-
2147-
node: PostgresNode = None
2164+
attempt = 0
2165+
ports = []
21482166
try:
2149-
node = node_app.make_simple("node", port=port)
2150-
assert node is not None
2151-
assert isinstance(node, PostgresNode)
2152-
assert node.os_ops is node_svc.os_ops
2153-
assert node.port_manager is None # <---------
2154-
assert node.port == port
2155-
assert node._should_free_port == False # noqa: E712
2167+
while True:
2168+
if attempt == C_MAX_ATTEMPTS:
2169+
raise RuntimeError("Node did not start.")
21562170

2157-
assert type(node_app.nodes_to_cleanup) == list # noqa: E721
2158-
assert len(node_app.nodes_to_cleanup) == 1
2159-
assert node_app.nodes_to_cleanup[0] is node
2171+
attempt += 1
21602172

2161-
node.slow_start()
2162-
finally:
2163-
if node is not None:
2164-
node.stop()
2165-
node.free_port()
2173+
logging.info("------------- attempt #{}".format(
2174+
attempt
2175+
))
21662176

2167-
assert node._port is None
2168-
assert not node._should_free_port
2177+
port = node_app.port_manager.reserve_port()
2178+
assert type(port) == int # noqa: E721
2179+
assert port is not ports
21692180

2170-
node.cleanup(release_resources=True)
2181+
try:
2182+
ports.append(port)
2183+
except: # noqa: E722
2184+
node_app.port_manager.release_port(port)
2185+
raise
2186+
2187+
assert len(ports) == attempt
2188+
node_name = "node_{}".format(attempt)
2189+
2190+
logging.info("Node [{}] is creating...".format(node_name))
2191+
node = node_app.make_simple(node_name, port=port)
2192+
assert node is not None
2193+
assert isinstance(node, PostgresNode)
2194+
assert node.os_ops is node_svc.os_ops
2195+
assert node.port_manager is None # <---------
2196+
assert node.port == port
2197+
assert node._should_free_port == False # noqa: E712
2198+
2199+
assert type(node_app.nodes_to_cleanup) == list # noqa: E721
2200+
assert len(node_app.nodes_to_cleanup) == attempt
2201+
assert node_app.nodes_to_cleanup[-1] is node
2202+
2203+
assert node.status() == NodeStatus.Stopped
2204+
logging.info("Node is created")
2205+
2206+
logging.info("Try to start a node...")
2207+
try:
2208+
node.slow_start()
2209+
except StartNodeException as e:
2210+
logging.info("Exception ({}): {}".format(
2211+
type(e).__name__,
2212+
e
2213+
))
2214+
assert node.status() == NodeStatus.Stopped
2215+
node_app.port_manager.release_port(port)
2216+
continue
2217+
2218+
assert node.status() == NodeStatus.Running
2219+
logging.info("Node is started")
2220+
2221+
logging.info("Stop node")
2222+
node.stop()
2223+
assert node.status() == NodeStatus.Stopped
2224+
logging.info("Node is stopped")
2225+
2226+
logging.info("OK. Go home.")
2227+
assert node is not None
2228+
assert isinstance(node, PostgresNode)
2229+
assert node._port is not None
2230+
assert node._port == port
2231+
assert not node._should_free_port
2232+
break
2233+
finally:
2234+
while len(ports) > 0:
2235+
node_app.port_manager.release_port(ports.pop())
21712236

21722237
# -----------
21732238
logging.info("temp directory [{}] is deleting".format(tmp_dir))
2174-
node_svc.os_ops.rmdir(tmp_dir)
2239+
node_svc.os_ops.rmdirs(tmp_dir)
2240+
return
21752241

21762242
@staticmethod
21772243
def helper__get_node(

tests/test_testgres_local.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from src import StartNodeException
1313
from src import ExecUtilException
1414
from src import NodeApp
15+
from src import NodeStatus
1516
from src import scoped_config
1617
from src import get_new_node
1718
from src import get_bin_path
@@ -316,7 +317,7 @@ def test_port_conflict(self):
316317
assert (node2.port == node1.port)
317318

318319
node2.init()
319-
320+
assert (node2.status() == NodeStatus.Stopped)
320321
with pytest.raises(
321322
expected_exception=StartNodeException,
322323
match=re.escape("Cannot start node after multiple attempts.")
@@ -327,14 +328,16 @@ def test_port_conflict(self):
327328
assert (node2._should_free_port)
328329
assert (__class__.tagPortManagerProxy.sm_DummyPortCurrentUsage == 1)
329330
assert (__class__.tagPortManagerProxy.sm_DummyPortTotalUsage == C_COUNT_OF_BAD_PORT_USAGE)
330-
assert not (node2.is_started)
331+
assert (not node2.is_started)
332+
assert (node2.status() == NodeStatus.Stopped)
331333

332334
# node2 must release our dummyPort (node1.port)
333335
assert (__class__.tagPortManagerProxy.sm_DummyPortCurrentUsage == 0)
334336

335337
# node1 is still working
336338
assert (node1.port == node1_port_copy)
337339
assert (node1._should_free_port)
340+
assert (node1.status() == NodeStatus.Running)
338341
assert (rm_carriage_returns(node1.safe_psql("SELECT 3;")) == b'3\n')
339342

340343
def test_simple_with_bin_dir(self):

0 commit comments

Comments
 (0)