Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 67f23a7

Browse files
Merge branch 'master' into skip-ssl-check
2 parents fb6205d + 1c73113 commit 67f23a7

File tree

9 files changed

+141
-60
lines changed

9 files changed

+141
-60
lines changed

testgres/operations/local_ops.py

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -58,47 +58,55 @@ def _process_output(encoding, temp_file_path):
5858
output = output.decode(encoding)
5959
return output, None # In Windows stderr writing in stdout
6060

61-
def _run_command(self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding):
62-
"""Execute a command and return the process and its output."""
63-
if os.name == 'nt' and stdout is None: # Windows
64-
with tempfile.NamedTemporaryFile(mode='w+b', delete=False) as temp_file:
65-
stdout = temp_file
66-
stderr = subprocess.STDOUT
67-
process = subprocess.Popen(
68-
cmd,
69-
shell=shell,
70-
stdin=stdin or subprocess.PIPE if input is not None else None,
71-
stdout=stdout,
72-
stderr=stderr,
73-
)
74-
if get_process:
75-
return process, None, None
76-
temp_file_path = temp_file.name
77-
78-
# Wait process finished
79-
process.wait()
80-
81-
output, error = self._process_output(encoding, temp_file_path)
82-
return process, output, error
83-
else: # Other OS
61+
def _run_command__nt(self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding):
62+
with tempfile.NamedTemporaryFile(mode='w+b', delete=False) as temp_file:
63+
stdout = temp_file
64+
stderr = subprocess.STDOUT
8465
process = subprocess.Popen(
8566
cmd,
8667
shell=shell,
8768
stdin=stdin or subprocess.PIPE if input is not None else None,
88-
stdout=stdout or subprocess.PIPE,
89-
stderr=stderr or subprocess.PIPE,
69+
stdout=stdout,
70+
stderr=stderr,
9071
)
9172
if get_process:
9273
return process, None, None
93-
try:
94-
output, error = process.communicate(input=input.encode(encoding) if input else None, timeout=timeout)
95-
if encoding:
96-
output = output.decode(encoding)
97-
error = error.decode(encoding)
98-
return process, output, error
99-
except subprocess.TimeoutExpired:
100-
process.kill()
101-
raise ExecUtilException("Command timed out after {} seconds.".format(timeout))
74+
temp_file_path = temp_file.name
75+
76+
# Wait process finished
77+
process.wait()
78+
79+
output, error = self._process_output(encoding, temp_file_path)
80+
return process, output, error
81+
82+
def _run_command__generic(self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding):
83+
process = subprocess.Popen(
84+
cmd,
85+
shell=shell,
86+
stdin=stdin or subprocess.PIPE if input is not None else None,
87+
stdout=stdout or subprocess.PIPE,
88+
stderr=stderr or subprocess.PIPE,
89+
)
90+
if get_process:
91+
return process, None, None
92+
try:
93+
output, error = process.communicate(input=input.encode(encoding) if input else None, timeout=timeout)
94+
if encoding:
95+
output = output.decode(encoding)
96+
error = error.decode(encoding)
97+
return process, output, error
98+
except subprocess.TimeoutExpired:
99+
process.kill()
100+
raise ExecUtilException("Command timed out after {} seconds.".format(timeout))
101+
102+
def _run_command(self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding):
103+
"""Execute a command and return the process and its output."""
104+
if os.name == 'nt' and stdout is None: # Windows
105+
method = __class__._run_command__nt
106+
else: # Other OS
107+
method = __class__._run_command__generic
108+
109+
return method(self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding)
102110

103111
def exec_command(self, cmd, wait_exit=False, verbose=False, expect_error=False, encoding=None, shell=False,
104112
text=False, input=None, stdin=None, stdout=None, stderr=None, get_process=False, timeout=None,

testgres/operations/remote_ops.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,26 +68,26 @@ def exec_command(self, cmd, wait_exit=False, verbose=False, expect_error=False,
6868

6969
exit_status = process.returncode
7070

71-
if encoding:
72-
result = result.decode(encoding)
73-
error = error.decode(encoding)
74-
75-
if expect_error:
76-
raise Exception(result, error)
71+
assert type(result) == bytes # noqa: E721
72+
assert type(error) == bytes # noqa: E721
7773

7874
if not error:
79-
error_found = 0
75+
error_found = False
8076
else:
81-
error = normalize_error(error)
8277
error_found = exit_status != 0 or any(
83-
marker in error for marker in ['error', 'Permission denied', 'fatal', 'No such file or directory']
78+
marker in error for marker in [b'error', b'Permission denied', b'fatal', b'No such file or directory']
8479
)
8580

86-
if not ignore_errors and error_found:
87-
if isinstance(error, bytes):
88-
message = b"Utility exited with non-zero code. Error: " + error
89-
else:
90-
message = f"Utility exited with non-zero code. Error: {error}"
81+
assert type(error_found) == bool # noqa: E721
82+
83+
if encoding:
84+
result = result.decode(encoding)
85+
error = error.decode(encoding)
86+
87+
if not ignore_errors and error_found and not expect_error:
88+
error = normalize_error(error)
89+
assert type(error) == str # noqa: E721
90+
message = "Utility exited with non-zero code. Error: " + error
9191
raise ExecUtilException(message=message, command=cmd, exit_code=exit_status, out=result)
9292

9393
if verbose:

tests/__init__.py

Whitespace-only changes.

tests/helpers/__init__.py

Whitespace-only changes.

tests/helpers/run_conditions.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import pytest
2+
import platform
3+
4+
5+
class RunConditions:
6+
# It is not a test kit!
7+
__test__ = False
8+
9+
def skip_if_windows():
10+
if platform.system().lower() == "windows":
11+
pytest.skip("This test does not support Windows.")

tests/test_local.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import pytest
2+
3+
from testgres import ExecUtilException
4+
from testgres import LocalOperations
5+
6+
from .helpers.run_conditions import RunConditions
7+
8+
9+
class TestLocalOperations:
10+
11+
@pytest.fixture(scope="function", autouse=True)
12+
def setup(self):
13+
self.operations = LocalOperations()
14+
15+
def test_exec_command_success(self):
16+
"""
17+
Test exec_command for successful command execution.
18+
"""
19+
RunConditions.skip_if_windows()
20+
21+
cmd = "python3 --version"
22+
response = self.operations.exec_command(cmd, wait_exit=True, shell=True)
23+
24+
assert b'Python 3.' in response
25+
26+
def test_exec_command_failure(self):
27+
"""
28+
Test exec_command for command execution failure.
29+
"""
30+
RunConditions.skip_if_windows()
31+
32+
cmd = "nonexistent_command"
33+
while True:
34+
try:
35+
self.operations.exec_command(cmd, wait_exit=True, shell=True)
36+
except ExecUtilException as e:
37+
error = e.message
38+
break
39+
raise Exception("We wait an exception!")
40+
assert error == "Utility exited with non-zero code. Error `b'/bin/sh: 1: nonexistent_command: not found\\n'`"
41+
42+
def test_exec_command_failure__expect_error(self):
43+
"""
44+
Test exec_command for command execution failure.
45+
"""
46+
RunConditions.skip_if_windows()
47+
48+
cmd = "nonexistent_command"
49+
50+
exit_status, result, error = self.operations.exec_command(cmd, verbose=True, wait_exit=True, shell=True, expect_error=True)
51+
52+
assert error == b'/bin/sh: 1: nonexistent_command: not found\n'
53+
assert exit_status == 127
54+
assert result == b''

tests/test_remote.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,27 @@ def test_exec_command_failure(self):
3030
Test exec_command for command execution failure.
3131
"""
3232
cmd = "nonexistent_command"
33-
try:
34-
exit_status, result, error = self.operations.exec_command(cmd, verbose=True, wait_exit=True)
35-
except ExecUtilException as e:
36-
error = e.message
33+
while True:
34+
try:
35+
self.operations.exec_command(cmd, verbose=True, wait_exit=True)
36+
except ExecUtilException as e:
37+
error = e.message
38+
break
39+
raise Exception("We wait an exception!")
3740
assert error == 'Utility exited with non-zero code. Error: bash: line 1: nonexistent_command: command not found\n'
3841

42+
def test_exec_command_failure__expect_error(self):
43+
"""
44+
Test exec_command for command execution failure.
45+
"""
46+
cmd = "nonexistent_command"
47+
48+
exit_status, result, error = self.operations.exec_command(cmd, verbose=True, wait_exit=True, shell=True, expect_error=True)
49+
50+
assert error == b'bash: line 1: nonexistent_command: command not found\n'
51+
assert exit_status == 127
52+
assert result == b''
53+
3954
def test_is_executable_true(self):
4055
"""
4156
Test is_executable for an existing executable.

tests/test_simple.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ def test_init_unique_system_id(self):
153153

154154
with scoped_config(cache_initdb=True,
155155
cached_initdb_unique=True) as config:
156-
157156
self.assertTrue(config.cache_initdb)
158157
self.assertTrue(config.cached_initdb_unique)
159158

@@ -376,21 +375,18 @@ def test_backup_multiple(self):
376375

377376
with node.backup(xlog_method='fetch') as backup1, \
378377
node.backup(xlog_method='fetch') as backup2:
379-
380378
self.assertNotEqual(backup1.base_dir, backup2.base_dir)
381379

382380
with node.backup(xlog_method='fetch') as backup:
383381
with backup.spawn_primary('node1', destroy=False) as node1, \
384382
backup.spawn_primary('node2', destroy=False) as node2:
385-
386383
self.assertNotEqual(node1.base_dir, node2.base_dir)
387384

388385
def test_backup_exhaust(self):
389386
with get_new_node() as node:
390387
node.init(allow_streaming=True).start()
391388

392389
with node.backup(xlog_method='fetch') as backup:
393-
394390
# exhaust backup by creating new node
395391
with backup.spawn_primary():
396392
pass
@@ -778,7 +774,6 @@ def test_pg_config(self):
778774

779775
# modify setting for this scope
780776
with scoped_config(cache_pg_config=False) as config:
781-
782777
# sanity check for value
783778
self.assertFalse(config.cache_pg_config)
784779

@@ -810,7 +805,6 @@ def test_config_stack(self):
810805
self.assertEqual(c1.cached_initdb_dir, d1)
811806

812807
with scoped_config(cached_initdb_dir=d2) as c2:
813-
814808
stack_size = len(testgres.config.config_stack)
815809

816810
# try to break a stack
@@ -840,7 +834,6 @@ def test_unix_sockets(self):
840834
def test_auto_name(self):
841835
with get_new_node().init(allow_streaming=True).start() as m:
842836
with m.replicate().start() as r:
843-
844837
# check that nodes are running
845838
self.assertTrue(m.status())
846839
self.assertTrue(r.status())

tests/test_simple_remote.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ def removing(f):
9494

9595

9696
class TestgresRemoteTests(unittest.TestCase):
97-
9897
def test_node_repr(self):
9998
with get_remote_node() as node:
10099
pattern = r"PostgresNode\(name='.+', port=.+, base_dir='.+'\)"
@@ -748,6 +747,7 @@ def test_pg_config(self):
748747

749748
# save right before config change
750749
c1 = get_pg_config()
750+
751751
# modify setting for this scope
752752
with scoped_config(cache_pg_config=False) as config:
753753
# sanity check for value

0 commit comments

Comments
 (0)