Skip to content

Commit 6a59a6b

Browse files
author
vshepard
committed
Add ability to run pg_probackup using valgrind
1 parent 0b9cc3f commit 6a59a6b

File tree

2 files changed

+71
-25
lines changed

2 files changed

+71
-25
lines changed

testgres/plugins/pg_probackup2/pg_probackup2/app.py

Lines changed: 69 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def __init__(self, test_class: unittest.TestCase,
6060
self.archive_compress = init_params.archive_compress
6161
self.test_class.output = None
6262
self.execution_time = None
63+
self.valgrind_sup_path = init_params.valgrind_sup_path
6364

6465
def form_daemon_process(self, cmdline, env):
6566
def stream_output(stream: subprocess.PIPE) -> None:
@@ -88,6 +89,7 @@ def stream_output(stream: subprocess.PIPE) -> None:
8889

8990
return self.process.pid
9091

92+
# ---- Start run function ---- #
9193
def run(self, command, gdb=False, old_binary=False, return_id=True, env=None,
9294
skip_log_directory=False, expect_error=False, use_backup_dir=True, daemonize=False):
9395
"""
@@ -98,53 +100,94 @@ def run(self, command, gdb=False, old_binary=False, return_id=True, env=None,
98100
gdb: when True it returns GDBObj(), when tuple('suspend', port) it runs probackup
99101
in suspended gdb mode with attachable gdb port, for local debugging
100102
"""
103+
command = self._add_backup_dir_to_cmd(command, use_backup_dir)
104+
# Old bin or regular one
105+
binary_path = self._get_binary_path(old_binary)
106+
107+
if not env:
108+
env = self.test_env
109+
# Add additional options if needed
110+
command, strcommand = self._add_options(command, skip_log_directory)
111+
112+
self.test_class.cmd = f"{binary_path} {strcommand}"
113+
if self.verbose:
114+
print(self.test_class.cmd)
115+
116+
cmdline = self._form_cmdline(binary_path, command)
117+
118+
if gdb is True:
119+
# general test flow for using GDBObj
120+
return GDBobj(cmdline, self.test_class)
121+
122+
return self._execute_command(cmdline, env, command, gdb, expect_error, return_id, daemonize)
123+
124+
def _add_backup_dir_to_cmd(self, command: list, use_backup_dir: TestBackupDir):
101125
if isinstance(use_backup_dir, TestBackupDir):
102-
command = [command[0], *use_backup_dir.pb_args, *command[1:]]
126+
return [command[0], *use_backup_dir.pb_args, *command[1:]]
103127
elif use_backup_dir:
104-
command = [command[0], *self.backup_dir.pb_args, *command[1:]]
128+
return [command[0], *self.backup_dir.pb_args, *command[1:]]
105129
else:
106-
command = [command[0], *self.backup_dir.pb_args[2:], *command[1:]]
107-
108-
if not self.probackup_old_path and old_binary:
109-
logging.error('PGPROBACKUPBIN_OLD is not set')
110-
exit(1)
130+
return [command[0], *self.backup_dir.pb_args[2:], *command[1:]]
111131

132+
def _get_binary_path(self, old_binary):
112133
if old_binary:
113-
binary_path = self.probackup_old_path
114-
else:
115-
binary_path = self.probackup_path
116-
117-
if not env:
118-
env = self.test_env
134+
if not self.probackup_old_path:
135+
logging.error('PGPROBACKUPBIN_OLD is not set')
136+
exit(1)
137+
return self.probackup_old_path
138+
return self.probackup_path
119139

140+
def _add_options(self, command: list, skip_log_directory: bool):
120141
strcommand = ' '.join(str(p) for p in command)
142+
121143
if '--log-level-file' in strcommand and \
122144
'--log-directory' not in strcommand and \
123145
not skip_log_directory:
124-
command += ['--log-directory=' + self.pb_log_path]
125-
strcommand += ' ' + command[-1]
146+
log_arg = f'--log-directory={self.pb_log_path}'
147+
command = command + [log_arg]
148+
strcommand += f' {log_arg}'
126149

127150
if 'pglz' in strcommand and \
128-
' -j' not in strcommand and '--thread' not in strcommand:
129-
command += ['-j', '1']
151+
' -j' not in strcommand and \
152+
'--thread' not in strcommand:
153+
command = command + ['-j', '1']
130154
strcommand += ' -j 1'
131155

132-
self.test_class.cmd = binary_path + ' ' + strcommand
133-
if self.verbose:
134-
print(self.test_class.cmd)
156+
return command, strcommand
135157

158+
def _form_cmdline(self, binary_path, command):
136159
cmdline = [binary_path, *command]
137-
if gdb is True:
138-
# general test flow for using GDBObj
139-
return GDBobj(cmdline, self.test_class)
140160

161+
if self.valgrind_sup_path and command[0] != "--version":
162+
os.makedirs(self.pb_log_path, exist_ok=True)
163+
if self.valgrind_sup_path and not os.path.isfile(self.valgrind_sup_path):
164+
raise FileNotFoundError(f"PG_PROBACKUP_VALGRIND_SUP should contain path to valgrind suppression file, "
165+
f"but found: {self.valgrind_sup_path}")
166+
valgrind_cmd = [
167+
"valgrind",
168+
"--gen-suppressions=all",
169+
"--leak-check=full",
170+
"--show-reachable=yes",
171+
"--error-limit=no",
172+
"--show-leak-kinds=all",
173+
"--errors-for-leak-kinds=all",
174+
"--error-exitcode=0",
175+
f"--log-file={os.path.join(self.pb_log_path, f'valgrind-{command[0]}-%p.log')}",
176+
f"--suppressions={self.valgrind_sup_path}",
177+
"--"
178+
]
179+
cmdline = valgrind_cmd + cmdline
180+
181+
return cmdline
182+
183+
def _execute_command(self, cmdline, env, command, gdb, expect_error, return_id, daemonize):
141184
try:
142-
if type(gdb) is tuple and gdb[0] == 'suspend':
143-
# special test flow for manually debug probackup
185+
if isinstance(gdb, tuple) and gdb[0] == 'suspend':
144186
gdb_port = gdb[1]
145187
cmdline = ['gdbserver'] + ['localhost:' + str(gdb_port)] + cmdline
146188
logging.warning("pg_probackup gdb suspended, waiting gdb connection on localhost:{0}".format(gdb_port))
147189

190+
# Execute command
148191
start_time = time.time()
149192
if daemonize:
150193
return self.form_daemon_process(cmdline, env)
@@ -174,6 +217,7 @@ def run(self, command, gdb=False, old_binary=False, return_id=True, env=None,
174217
return self.test_class.output
175218
else:
176219
raise ProbackupException(self.test_class.output, self.test_class.cmd)
220+
# ---- End run function ---- #
177221

178222
def get_backup_id(self):
179223
if init_params.major_version > 2:

testgres/plugins/pg_probackup2/pg_probackup2/init_helpers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ def __init__(self):
214214
else:
215215
raise Exception('Can\'t process pg_probackup version \"{}\": the major version is expected to be a number'.format(self.probackup_version))
216216

217+
self.valgrind_sup_path = test_env.get('PG_PROBACKUP_VALGRIND_SUP', None)
218+
217219
def test_env(self):
218220
return self._test_env.copy()
219221

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