mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2026-10-28 23:50:04 -05:00
fix: ImportExportServersTestCase uses sys.executable + surfaces subprocess errors
Two latent bugs in pgadmin/setup/tests/test_export_import_servers.py
caused this test to fail on macOS / modern Linux distros:
1. The test invoked the subprocesses with a hardcoded "python" via
os.system. macOS and many modern Linux distros do not provide a
"python" alias — only "python3" or a venv-specific binary. The
subprocess fails with "sh: python: command not found", exits non-
zero, and writes nothing to the dump-servers output file.
Same root cause that a50a553b0 ("chore: feature tests use
sys.executable") fixed for AppStarter; this is the same fix in the
regression test.
2. Both os.system calls redirected stderr to /dev/null. When the
subprocess failed the empty output file then tripped json.loads
with the misleading "Expecting value: line 1 column 1 (char 0)"
instead of surfacing the underlying "command not found" error.
Switch to subprocess.run with a list (so there is no shell quoting and
no command-injection surface), use sys.executable, capture stderr, and
self.fail() with the captured stderr if the subprocess exits non-zero.
Verified: setup.tests goes from 4 pass / 1 fail / 1 skip to 5 pass / 0
fail / 1 skip on PG18.
This commit is contained in:
1 parent
9923eefcab
commit
208541cc48
1 file changed
+29
-6
@@ -10,6 +10,8 @@
|
|||||||
from pgadmin.utils.route import BaseTestGenerator
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import config
|
import config
|
||||||
|
|
||||||
@@ -34,16 +36,37 @@ class ImportExportServersTestCase(BaseTestGenerator):
|
|||||||
path = os.path.dirname(__file__)
|
path = os.path.dirname(__file__)
|
||||||
setup = os.path.realpath(os.path.join(path, "../../../setup.py"))
|
setup = os.path.realpath(os.path.join(path, "../../../setup.py"))
|
||||||
|
|
||||||
# Load the servers
|
# Use sys.executable instead of bare "python" — macOS / many Linux
|
||||||
os.system(
|
# distros do not provide a "python" alias, only "python3" or a venv-
|
||||||
"python \"%s\" load-servers \"%s\" 2> %s" %
|
# specific binary. Use subprocess.run with a list so there is no
|
||||||
(setup, os.path.join(path, "servers.json"), os.devnull)
|
# shell quoting and no command injection surface. Surface the
|
||||||
|
# subprocess error directly instead of letting a silent failure
|
||||||
|
# produce an empty file that downstream json.loads then misreports
|
||||||
|
# as "Expecting value: line 1 column 1".
|
||||||
|
load_result = subprocess.run(
|
||||||
|
[sys.executable, setup, "load-servers",
|
||||||
|
os.path.join(path, "servers.json")],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
)
|
)
|
||||||
|
if load_result.returncode != 0:
|
||||||
|
self.fail(
|
||||||
|
"load-servers exited {0}: {1}".format(
|
||||||
|
load_result.returncode, load_result.stderr))
|
||||||
|
|
||||||
# And dump them again
|
# And dump them again
|
||||||
tf = tempfile.NamedTemporaryFile(delete=False)
|
tf = tempfile.NamedTemporaryFile(delete=False)
|
||||||
os.system("python \"%s\" dump-servers \"%s\" 2> %s" %
|
dump_result = subprocess.run(
|
||||||
(setup, tf.name, os.devnull))
|
[sys.executable, setup, "dump-servers", tf.name],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
if dump_result.returncode != 0:
|
||||||
|
self.fail(
|
||||||
|
"dump-servers exited {0}: {1}".format(
|
||||||
|
dump_result.returncode, dump_result.stderr))
|
||||||
|
|
||||||
# Compare the JSON files, ignoring servers that exist in our
|
# Compare the JSON files, ignoring servers that exist in our
|
||||||
# generated file but not the test config (they are likely
|
# generated file but not the test config (they are likely
|
||||||
|
|||||||
Reference in new issue
Block a user