mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-10-30 09:38:23 -04:00
* testsuite: fix fleettest example json for IDN match CI for IDN tests * testsuite: fix fleettest example skip extras and pin Cygwin python #1069 replaced daemon-max-alloc-zero with max-alloc-zero, which no longer needs the old static client, but the per-box expect_skip_extra entries still named the old test, so runtests refused the skip list ("no such test") on every Linux target. Drop those entries. Pin python3.9 on the cygwin target to match the workflow, which installs only python39: the box's default python3 (3.12) has a working AF_UNIX socketpair, so daemon-stdin-local-socket ran where cygwin.txt expects a skip. Note that python39 must be 3.9.25+ for os.getxattr, which the xattr tests need to run as they do in CI. * testsuite: run bash without POSIXLY_CORRECT; tolerate Cygwin symlink copystat runtests.py exports POSIXLY_CORRECT=1 to every test, and bash before 5.1 disables process substitution in POSIX mode, so pseudo-paths, pseudo-paths-daemon and read-batch-pipe silently skipped on bash 4.4/5.0 hosts (Ubuntu 18.04/20.04, AlmaLinux 8). Strip the variable from bash's environment: the tests require bash precisely for that syntax. That was also why they skipped in the AlmaLinux 8 CI container, so its skip list (which held only those three) goes away along with the workflow's reference to it. The macOS list keeps them: there they skip as Linux-only. malicious-sender-delete-scope copies the source tree with symlinks=True. Cygwin's python 3.9.25 gained os.listxattr, and copystat() on a fresh symlink then fails with EACCES, although the link itself was created. Ignore copytree errors that are only about symlink pairs; anything else still raises. * testsuite: update max-alloc entry
86 lines
2.9 KiB
Python
86 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
"""--read-batch process substitution /dev/fd/ pipe must not crash with strict file-type checks."""
|
|
import os
|
|
import shlex
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from rsyncfns import SCRATCHDIR, makepath, rmtree, rsync_argv, test_fail, test_skipped
|
|
|
|
# We require bash specifically because standard POSIX /bin/sh does not
|
|
# guarantee support for <(...) process substitution syntax.
|
|
if not sys.platform.startswith('linux'):
|
|
test_skipped('This test requires Linux platform')
|
|
|
|
bash = shutil.which('bash')
|
|
if bash is None:
|
|
test_skipped('bash is unavailable, cannot test process substitution')
|
|
|
|
# runtests.py exports POSIXLY_CORRECT=1, and bash before 5.1 disables process
|
|
# substitution in POSIX mode -- the very syntax bash is required for here.
|
|
bash_env = {k: v for k, v in os.environ.items() if k != 'POSIXLY_CORRECT'}
|
|
# Verify the host bash actually supports process substitution
|
|
probe = subprocess.run(
|
|
[bash, '-c', 'cat <(echo "probe")'],
|
|
env=bash_env,
|
|
capture_output=True)
|
|
|
|
if probe.returncode != 0:
|
|
test_skipped('bash process substitution is not supported on this system')
|
|
|
|
base = Path(SCRATCHDIR / 'rsync-batch-fifo')
|
|
src = base / 'src'
|
|
dest = base / 'dest'
|
|
batch_file = base / 'update.batch'
|
|
makepath(src, dest)
|
|
|
|
# 1. Create dummy data
|
|
(src / 'payload.txt').write_text('batch payload data\n')
|
|
|
|
# 2. Generate a valid batch file so `cat` actually has a real file to read.
|
|
# Note: This operation also copies the file to `dest` as a side effect.
|
|
subprocess.run([*rsync_argv('-a', f'--write-batch={batch_file}'), f'{src}/', f'{dest}/'], check=True)
|
|
|
|
# must wipe and recreate the destination directory so the test can
|
|
# properly prove that --read-batch recreates the files from scratch.
|
|
rmtree(dest)
|
|
makepath(dest)
|
|
|
|
# 3. Now we can test reading it via bash process substitution
|
|
rsync_base_cmd = shlex.join(rsync_argv('-a'))
|
|
batch_path = shlex.quote(str(batch_file))
|
|
dest_path = shlex.quote(str(dest) + '/')
|
|
|
|
# Construct the bash command: rsync -a --read-batch=<(cat /path/to/batch) /dest/
|
|
bash_script = f"{rsync_base_cmd} --read-batch=<(cat {batch_path}) {dest_path}"
|
|
|
|
try:
|
|
proc_read = subprocess.run(
|
|
[bash, '-c', bash_script],
|
|
capture_output=True,
|
|
env=bash_env,
|
|
text=True,
|
|
timeout=10,
|
|
)
|
|
except subprocess.TimeoutExpired:
|
|
rmtree(base)
|
|
test_fail('process substitution batch test timed out')
|
|
|
|
ctx = f'rc={proc_read.returncode}, stderr={proc_read.stderr.strip()!r}'
|
|
|
|
# Evaluate result against the strict S_ISREG check bug
|
|
if proc_read.returncode != 0:
|
|
rmtree(base)
|
|
test_fail(f'rsync crashed reading batch file from pipe ({ctx})')
|
|
|
|
if not (dest / 'payload.txt').is_file():
|
|
rmtree(base)
|
|
test_fail(f'rsync exited successfully but payload is missing in target ({ctx})')
|
|
|
|
rmtree(base)
|
|
print('rsync successfully parsed batch stream via process substitution pseudo-path')
|
|
raise SystemExit(0)
|