Skip to content

Commit 4ab9420

Browse files
Detect port leaks in tests (#414)
run_tests.sh now checks that all the ports were released. Updated tests: - TestTestgresCommon::test_node_constructor__default - TestTestgresCommon::test_kill__ok - TestTestgresRemote::test_init__unk_LANG_and_LC_CTYPE
1 parent 23f5584 commit 4ab9420

3 files changed

Lines changed: 86 additions & 21 deletions

File tree

run_tests.sh

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,45 +37,105 @@ if [ -n "${TEST_CFG__REMOTE_HOST:-}" ] && [ -n "${TEST_CFG__REMOTE_USERNAME:-}"
3737
[ -n "${TEST_CFG__REMOTE_SSH_KEY:-}" ] && cmd_str="$cmd_str -i \"$TEST_CFG__REMOTE_SSH_KEY\""
3838
[ -n "${TEST_CFG__REMOTE_PORT:-}" ] && cmd_str="$cmd_str -p \"$TEST_CFG__REMOTE_PORT\""
3939

40-
cmd_str="$cmd_str \"$TEST_CFG__REMOTE_USERNAME@$TEST_CFG__REMOTE_HOST\" 'df -T'"
41-
REMOTE_FS_STATE_QUERY="$cmd_str"
40+
REMOTE_SSH_PREFIX="$cmd_str \"$TEST_CFG__REMOTE_USERNAME@$TEST_CFG__REMOTE_HOST\""
4241
else
43-
REMOTE_FS_STATE_QUERY=""
42+
REMOTE_SSH_PREFIX=""
4443
fi
4544

46-
show_fs_state() {
47-
df -T
48-
if [ -n "$REMOTE_FS_STATE_QUERY" ]; then
49-
eval "$REMOTE_FS_STATE_QUERY"
45+
exec_command() {
46+
local cmd="$1"
47+
local prefix="$2"
48+
49+
eval "$prefix $cmd"
50+
}
51+
52+
show_fs_state__impl() {
53+
local prefix="$1"
54+
local host_label="$2"
55+
56+
set +x
57+
echo "------------- ${host_label} FS STATE"
58+
set -x
59+
exec_command "df -T" "$prefix"
60+
}
61+
62+
check_leftover_ports__impl() {
63+
local prefix="$1"
64+
local host_label="$2"
65+
local ports_dir="/tmp/testgres/ports"
66+
67+
set +x
68+
echo "------------- Checking ${host_label} ports lock directory"
69+
set -x
70+
71+
# Check command: will print FOUND if the directory exists and is not empty
72+
local check_cmd="if [ -d '${ports_dir}' ] && [ \"\$(ls -A '${ports_dir}' 2>/dev/null)\" ]; then echo 'FOUND'; fi"
73+
74+
# Temporarily disable bash's instant drop (set +e) to safely intercept the result
75+
set +e
76+
local result
77+
result=$(exec_command "$check_cmd" "$prefix")
78+
set -e
79+
80+
set +x
81+
if [ "$result" = "FOUND" ]; then
82+
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
83+
echo "ERROR: Leftover ports detected in $ports_dir on $host_label machine!"
84+
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
85+
set -x
86+
87+
# We display a list of frozen ports so that the culprits can be identified
88+
exec_command "ls -la '$ports_dir'" "$prefix"
89+
90+
# We hard-drop the entire control script
91+
# sleep 3600
92+
exit 1
93+
else
94+
echo "Clear. No leftover port locks."
95+
fi
96+
set -x
97+
}
98+
99+
fs_verification__impl() {
100+
show_fs_state__impl "$1" "$2"
101+
102+
check_leftover_ports__impl "$1" "$2"
103+
}
104+
105+
fs_verification() {
106+
fs_verification__impl "" "LOCAL"
107+
108+
if [ -n "$REMOTE_SSH_PREFIX" ]; then
109+
fs_verification__impl "$REMOTE_SSH_PREFIX" "REMOTE"
50110
fi
51111
}
52112

53113
# ---------------------------------------- PATH
54114

55-
show_fs_state
115+
fs_verification
56116

57117
# run tests (PATH)
58118
time coverage run -a -m pytest -l -vvv -n 4 -k "${TEST_FILTER}"
59119

60120
# ---------------------------------------- PG_BIN
61121

62-
show_fs_state
122+
fs_verification
63123

64124
# run tests (PG_BIN)
65125
PG_BIN=$(pg_config --bindir) \
66126
time coverage run -a -m pytest -l -vvv -n 4 -k "${TEST_FILTER}"
67127

68128
# ---------------------------------------- PG_CONFIG
69129

70-
show_fs_state
130+
fs_verification
71131

72132
# run tests (PG_CONFIG)
73133
PG_CONFIG=$(pg_config --bindir)/pg_config \
74134
time coverage run -a -m pytest -l -vvv -n 4 -k "${TEST_FILTER}"
75135

76136
# ---------------------------------------- pg8000
77137

78-
show_fs_state
138+
fs_verification
79139

80140
# test pg8000
81141
pip uninstall -y psycopg2
@@ -85,7 +145,7 @@ time coverage run -a -m pytest -l -vvv -n 4 -k "${TEST_FILTER}"
85145

86146
# ---------------------------------------- finish
87147

88-
show_fs_state
148+
fs_verification
89149

90150
# ---------------------------------------- coverage
91151

tests/test_testgres_common.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -190,15 +190,15 @@ def test_default_username2(
190190
return
191191

192192
def test_node_constructor__default(self):
193-
node = PostgresNode()
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
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
202202
return
203203

204204
def test_node_constructor__host(self):
@@ -771,6 +771,8 @@ def test_kill__ok(
771771
finally:
772772
if node.is_started:
773773
node.stop()
774+
775+
node.cleanup(release_resources=True)
774776
return
775777

776778
def test_kill_backgroud_writer__ok(

tests/test_testgres_remote.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ def test_init__unk_LANG_and_LC_CTYPE(self):
8282
assert isinstance(node_version, Version)
8383

8484
if node.version < Version("11"):
85+
node.cleanup(release_resources=True)
8586
pytest.skip("This test does not work on old PG10-.")
8687

8788
try:
@@ -152,6 +153,8 @@ def test_init__unk_LANG_and_LC_CTYPE(self):
152153
assert expectedMsg2 in exc.error
153154
continue
154155

156+
node.cleanup(release_resources=True)
157+
155158
if not errorIsDetected:
156159
pytest.xfail("All the bad data are processed without errors!")
157160

0 commit comments

Comments
 (0)