mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-11-01 17:49:56 -05:00
Use a level-aware compressor for the compress-options --compress-level check. The default compressor can be lz4, which has no tunable compression levels and therefore reports level 0. Select zlibx or zlib for this subtest so it verifies that --compress-level is passed to a compressor that supports levels. Read the build config when setting up the symlink-placeholder test. The t_symlink_secure helper is compiled against the build directory config.h; use that same config for the Python test setup so it creates the symlink placeholder PoC inputs when the compiled helper will exercise them.
89 lines
3.8 KiB
Python
89 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Breadth coverage of the algorithm-selection options at depth:
|
|
--compress-choice / --compress-level / --skip-compress and
|
|
--checksum-choice / --checksum-seed.
|
|
|
|
Compression and checksum choice don't change the result, so each available
|
|
algorithm is exercised for a clean, byte-identical transfer of a >=3-deep tree
|
|
(proving the option parses, negotiates and doesn't corrupt data).
|
|
"""
|
|
|
|
import json
|
|
import re
|
|
|
|
from rsyncfns import (
|
|
FROMDIR, TODIR,
|
|
assert_same, make_tree, rmtree, run_rsync, test_fail, walk_files,
|
|
)
|
|
|
|
src = FROMDIR
|
|
vv = json.loads(run_rsync('-VV', check=True, capture_output=True).stdout)
|
|
compressors = [a for a in vv.get('compress_list', []) if a != 'none']
|
|
checksums = [a for a in vv.get('checksum_list', []) if a != 'none']
|
|
|
|
|
|
def fresh():
|
|
rmtree(src)
|
|
rmtree(TODIR)
|
|
make_tree(src, depth=3, data=True, data_size=4096)
|
|
return [p.relative_to(src) for p in walk_files(src)]
|
|
|
|
|
|
def verify(rels, label):
|
|
for rel in rels:
|
|
assert_same(TODIR / rel, src / rel, label=f'{label} {rel}')
|
|
|
|
|
|
# --- --compress-choice for every advertised compressor ----------------------
|
|
# Byte-identical output alone proves only that the option didn't corrupt data;
|
|
# assert via --debug=NSTR (compat.c) that the requested compressor was actually
|
|
# selected for the transfer. The trailing " (level" anchors so zlib != zlibx.
|
|
for algo in compressors:
|
|
rels = fresh()
|
|
proc = run_rsync('-az', f'--compress-choice={algo}', '--debug=NSTR',
|
|
f'{src}/', f'{TODIR}/', capture_output=True)
|
|
if not re.search(rf'compress: {re.escape(algo)} \(level', proc.stdout):
|
|
test_fail(f"--compress-choice={algo} was not the selected compressor; "
|
|
f"--debug=NSTR output:\n{proc.stdout}")
|
|
verify(rels, f'--compress-choice={algo}')
|
|
|
|
# --- --compress-level (the requested level reaches the compressor) ----------
|
|
rels = fresh()
|
|
# The default compressor can be lz4, which has no tunable levels and reports
|
|
# level 0; pick a level-aware compressor so this verifies --compress-level reaches
|
|
# a compressor that supports it.
|
|
level_algo = next((a for a in ('zlibx', 'zlib') if a in compressors), None)
|
|
level_args = [f'--compress-choice={level_algo}'] if level_algo else []
|
|
proc = run_rsync('-az', *level_args, '--compress-level=9', '--debug=NSTR',
|
|
f'{src}/', f'{TODIR}/', capture_output=True)
|
|
if not re.search(r'compress: \S+ \(level 9\)', proc.stdout):
|
|
test_fail("--compress-level=9 was not applied; "
|
|
f"--debug=NSTR output:\n{proc.stdout}")
|
|
verify(rels, '--compress-level=9')
|
|
|
|
# --- --skip-compress (the file must still arrive intact) --------------------
|
|
rels = fresh()
|
|
(src / 'd1' / 'd2' / 'x.gz').write_bytes(b'\x1f\x8b' + b'pseudo gzip body ' * 64)
|
|
run_rsync('-az', '--skip-compress=gz', f'{src}/', f'{TODIR}/')
|
|
assert_same(TODIR / 'd1' / 'd2' / 'x.gz', src / 'd1' / 'd2' / 'x.gz',
|
|
label='--skip-compress gz')
|
|
|
|
# --- --checksum-choice for every advertised checksum ------------------------
|
|
# As above: assert via --debug=NSTR (checksum.c) that the requested checksum was
|
|
# the one negotiated, not merely that the transfer succeeded.
|
|
for algo in checksums:
|
|
rels = fresh()
|
|
proc = run_rsync('-a', '-c', f'--checksum-choice={algo}', '--debug=NSTR',
|
|
f'{src}/', f'{TODIR}/', capture_output=True)
|
|
if not re.search(rf'checksum: {re.escape(algo)}\b', proc.stdout):
|
|
test_fail(f"--checksum-choice={algo} was not the selected checksum; "
|
|
f"--debug=NSTR output:\n{proc.stdout}")
|
|
verify(rels, f'--checksum-choice={algo}')
|
|
|
|
# --- --checksum-seed --------------------------------------------------------
|
|
rels = fresh()
|
|
run_rsync('-a', '-c', '--checksum-seed=12345', f'{src}/', f'{TODIR}/')
|
|
verify(rels, '--checksum-seed')
|
|
|
|
print("compress-options: compress/checksum algorithm selection verified at depth")
|