Skip to content

Commit 05cd996

Browse files
author
vshepard
committed
Fix initdb error on Windows - fix pgbench
1 parent edb5708 commit 05cd996

File tree

8 files changed

+71
-69
lines changed

8 files changed

+71
-69
lines changed

testgres/helpers/__init__.py

Whitespace-only changes.

testgres/helpers/port_manager.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import socket
2+
import random
3+
from typing import Set, Iterable, Optional
4+
5+
6+
class PortForException(Exception):
7+
pass
8+
9+
10+
class PortManager:
11+
def __init__(self, ports_range=(1024, 65535)):
12+
self.ports_range = ports_range
13+
14+
@staticmethod
15+
def is_port_free(port: int) -> bool:
16+
"""Check if a port is free to use."""
17+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
18+
try:
19+
s.bind(("", port))
20+
return True
21+
except OSError:
22+
return False
23+
24+
def find_free_port(self, ports: Optional[Set[int]] = None, exclude_ports: Optional[Iterable[int]] = None) -> int:
25+
"""Return a random unused port number."""
26+
if ports is None:
27+
ports = set(range(1024, 65535))
28+
29+
if exclude_ports is None:
30+
exclude_ports = set()
31+
32+
ports.difference_update(set(exclude_ports))
33+
34+
sampled_ports = random.sample(tuple(ports), min(len(ports), 100))
35+
36+
for port in sampled_ports:
37+
if self.is_port_free(port):
38+
return port
39+
40+
raise PortForException("Can't select a port")

testgres/operations/local_ops.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,7 @@ def _run_command(cmd, shell, input, timeout, encoding, temp_file=None):
5555
stdout=stdout,
5656
stderr=stderr,
5757
)
58-
59-
try:
60-
return process.communicate(input=input.encode(encoding) if input else None, timeout=timeout), process
61-
except subprocess.TimeoutExpired:
62-
process.kill()
63-
raise ExecUtilException("Command timed out after {} seconds.".format(timeout))
58+
return process
6459

6560
@staticmethod
6661
def _raise_exec_exception(message, command, exit_code, output):
@@ -151,10 +146,12 @@ def _exec_command_windows(self, cmd, wait_exit=False, verbose=False,
151146
input=None, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
152147
get_process=None, timeout=None):
153148
with tempfile.NamedTemporaryFile(mode='w+b') as temp_file:
154-
_, process = self._run_command(cmd, shell, input, timeout, encoding, temp_file)
155-
if get_process:
156-
return process
157-
output = self._process_output(process, encoding, temp_file)
149+
process = self._run_command(cmd, shell, input, timeout, encoding, temp_file)
150+
try:
151+
output = process.communicate(input=input.encode(encoding) if input else None, timeout=timeout)
152+
except subprocess.TimeoutExpired:
153+
process.kill()
154+
raise ExecUtilException("Command timed out after {} seconds.".format(timeout))
158155

159156
if process.returncode != 0 or has_errors(output):
160157
if process.returncode == 0:

testgres/operations/remote_ops.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ def __init__(self, conn_params: ConnectionParams):
4545
self.conn_params = conn_params
4646
self.host = conn_params.host
4747
self.ssh_key = conn_params.ssh_key
48+
if self.ssh_key:
49+
self.ssh_cmd = ["-i", self.ssh_key]
50+
else:
51+
self.ssh_cmd = []
4852
self.remote = True
4953
self.username = conn_params.username or self.get_user()
5054
self.add_known_host(self.host)
@@ -91,9 +95,9 @@ def exec_command(self, cmd, wait_exit=False, verbose=False, expect_error=False,
9195
"""
9296
ssh_cmd = []
9397
if isinstance(cmd, str):
94-
ssh_cmd = ['ssh', f"{self.username}@{self.host}", '-i', self.ssh_key, cmd]
98+
ssh_cmd = ['ssh', f"{self.username}@{self.host}"] + self.ssh_cmd + [cmd]
9599
elif isinstance(cmd, list):
96-
ssh_cmd = ['ssh', f"{self.username}@{self.host}", '-i', self.ssh_key] + cmd
100+
ssh_cmd = ['ssh', f"{self.username}@{self.host}"] + self.ssh_cmd + cmd
97101
process = subprocess.Popen(ssh_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
98102
if get_process:
99103
return process
@@ -242,9 +246,9 @@ def mkdtemp(self, prefix=None):
242246
- prefix (str): The prefix of the temporary directory name.
243247
"""
244248
if prefix:
245-
command = ["ssh", "-i", self.ssh_key, f"{self.username}@{self.host}", f"mktemp -d {prefix}XXXXX"]
249+
command = ["ssh"] + self.ssh_cmd + [f"{self.username}@{self.host}", f"mktemp -d {prefix}XXXXX"]
246250
else:
247-
command = ["ssh", "-i", self.ssh_key, f"{self.username}@{self.host}", "mktemp -d"]
251+
command = ["ssh"] + self.ssh_cmd + [f"{self.username}@{self.host}", "mktemp -d"]
248252

249253
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
250254

@@ -288,7 +292,7 @@ def write(self, filename, data, truncate=False, binary=False, read_and_write=Fal
288292

289293
with tempfile.NamedTemporaryFile(mode=mode, delete=False) as tmp_file:
290294
if not truncate:
291-
scp_cmd = ['scp', '-i', self.ssh_key, f"{self.username}@{self.host}:{filename}", tmp_file.name]
295+
scp_cmd = ['scp'] + self.ssh_cmd + [f"{self.username}@{self.host}:{filename}", tmp_file.name]
292296
subprocess.run(scp_cmd, check=False) # The file might not exist yet
293297
tmp_file.seek(0, os.SEEK_END)
294298

@@ -304,12 +308,11 @@ def write(self, filename, data, truncate=False, binary=False, read_and_write=Fal
304308
tmp_file.write(data)
305309

306310
tmp_file.flush()
307-
308-
scp_cmd = ['scp', '-i', self.ssh_key, tmp_file.name, f"{self.username}@{self.host}:{filename}"]
311+
scp_cmd = ['scp'] + self.ssh_cmd + [tmp_file.name, f"{self.username}@{self.host}:{filename}"]
309312
subprocess.run(scp_cmd, check=True)
310313

311314
remote_directory = os.path.dirname(filename)
312-
mkdir_cmd = ['ssh', '-i', self.ssh_key, f"{self.username}@{self.host}", f"mkdir -p {remote_directory}"]
315+
mkdir_cmd = ['ssh'] + self.ssh_cmd + [f"{self.username}@{self.host}", f"mkdir -p {remote_directory}"]
313316
subprocess.run(mkdir_cmd, check=True)
314317

315318
os.remove(tmp_file.name)
@@ -374,7 +377,7 @@ def get_pid(self):
374377
return int(self.exec_command("echo $$", encoding=get_default_encoding()))
375378

376379
def get_process_children(self, pid):
377-
command = ["ssh", "-i", self.ssh_key, f"{self.username}@{self.host}", f"pgrep -P {pid}"]
380+
command = ["ssh"] + self.ssh_cmd + [f"{self.username}@{self.host}", f"pgrep -P {pid}"]
378381

379382
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
380383

testgres/utils.py

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,16 @@
44
from __future__ import print_function
55

66
import os
7-
import random
8-
import socket
97

108
import sys
119

1210
from contextlib import contextmanager
1311
from packaging.version import Version, InvalidVersion
1412
import re
1513

16-
from port_for import PortForException
1714
from six import iteritems
1815

16+
from helpers.port_manager import PortManager
1917
from .exceptions import ExecUtilException
2018
from .config import testgres_config as tconf
2119

@@ -40,49 +38,13 @@ def reserve_port():
4038
"""
4139
Generate a new port and add it to 'bound_ports'.
4240
"""
43-
port = select_random(exclude_ports=bound_ports)
41+
port_mng = PortManager()
42+
port = port_mng.find_free_port(exclude_ports=bound_ports)
4443
bound_ports.add(port)
4544

4645
return port
4746

4847

49-
def select_random(
50-
ports=None,
51-
exclude_ports=None,
52-
) -> int:
53-
"""
54-
Return random unused port number.
55-
Standard function from port_for does not work on Windows because of error
56-
'port_for.exceptions.PortForException: Can't select a port'
57-
We should update it.
58-
"""
59-
if ports is None:
60-
ports = set(range(1024, 65535))
61-
62-
if exclude_ports is None:
63-
exclude_ports = set()
64-
65-
ports.difference_update(set(exclude_ports))
66-
67-
sampled_ports = random.sample(tuple(ports), min(len(ports), 100))
68-
69-
for port in sampled_ports:
70-
if is_port_free(port):
71-
return port
72-
73-
raise PortForException("Can't select a port")
74-
75-
76-
def is_port_free(port: int) -> bool:
77-
"""Check if a port is free to use."""
78-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
79-
try:
80-
s.bind(("", port))
81-
return True
82-
except OSError:
83-
return False
84-
85-
8648
def release_port(port):
8749
"""
8850
Free port provided by reserve_port().

tests/test_remote.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@ class TestRemoteOperations:
1111

1212
@pytest.fixture(scope="function", autouse=True)
1313
def setup(self):
14-
conn_params = ConnectionParams(host=os.getenv('RDBMS_TESTPOOL1_HOST') or '172.18.0.3',
15-
username='dev',
16-
ssh_key=os.getenv(
17-
'RDBMS_TESTPOOL_SSHKEY') or '../../container_files/postgres/ssh/id_ed25519')
14+
conn_params = ConnectionParams(host=os.getenv('RDBMS_TESTPOOL1_HOST') or '127.0.0.1',
15+
username=os.getenv('USER'),
16+
ssh_key=os.getenv('RDBMS_TESTPOOL_SSHKEY'))
1817
self.operations = RemoteOperations(conn_params)
1918

2019
def test_exec_command_success(self):
@@ -41,7 +40,7 @@ def test_is_executable_true(self):
4140
"""
4241
Test is_executable for an existing executable.
4342
"""
44-
cmd = "postgres"
43+
cmd = os.getenv('PG_CONFIG')
4544
response = self.operations.is_executable(cmd)
4645

4746
assert response is True

tests/test_simple.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,8 @@ def test_pgbench(self):
763763
out, _ = proc.communicate()
764764
out = out.decode('utf-8')
765765

766+
proc.stdout.close()
767+
766768
self.assertTrue('tps' in out)
767769

768770
def test_pg_config(self):

tests/test_simple_remote.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,9 @@
5252
from testgres.utils import PgVer
5353
from testgres.node import ProcessProxy, ConnectionParams
5454

55-
conn_params = ConnectionParams(host=os.getenv('RDBMS_TESTPOOL1_HOST') or '172.18.0.3',
56-
username='dev',
57-
ssh_key=os.getenv(
58-
'RDBMS_TESTPOOL_SSHKEY') or '../../container_files/postgres/ssh/id_ed25519')
55+
conn_params = ConnectionParams(host=os.getenv('RDBMS_TESTPOOL1_HOST') or '127.0.0.1',
56+
username=os.getenv('USER'),
57+
ssh_key=os.getenv('RDBMS_TESTPOOL_SSHKEY'))
5958
os_ops = RemoteOperations(conn_params)
6059
testgres_config.set_os_ops(os_ops=os_ops)
6160

0 commit comments

Comments
 (0)
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