Skip to content

Commit fc41545

Browse files
committed
testsuite: Add a read-batch test
1 parent 4dfecc3 commit fc41545

3 files changed

Lines changed: 81 additions & 0 deletions

File tree

testsuite/read-batch-pipe_test.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/env python3
2+
"""--read-batch process substitution /dev/fd/ pipe must not crash with strict file-type checks."""
3+
4+
import os
5+
import shlex
6+
import shutil
7+
import subprocess
8+
import tempfile
9+
from pathlib import Path
10+
11+
from rsyncfns import SCRATCHDIR, makepath, rmtree, rsync_argv, test_fail, test_skipped
12+
13+
# We require bash specifically because standard POSIX /bin/sh does not
14+
# guarantee support for <(...) process substitution syntax.
15+
bash = shutil.which('bash')
16+
if bash is None:
17+
test_skipped('bash is unavailable, cannot test process substitution')
18+
19+
# Verify the host bash actually supports process substitution
20+
probe = subprocess.run(
21+
[bash, '-c', 'cat <(echo "probe")'],
22+
capture_output=True)
23+
24+
if probe.returncode != 0:
25+
test_skipped('bash process substitution is not supported on this system')
26+
27+
base = Path(SCRATCHDIR / 'rsync-batch-fifo')
28+
src = base / 'src'
29+
dest = base / 'dest'
30+
batch_file = base / 'update.batch'
31+
makepath(src, dest)
32+
33+
# 1. Create dummy data
34+
(src / 'payload.txt').write_text('batch payload data\n')
35+
36+
# 2. Generate a valid batch file so `cat` actually has a real file to read.
37+
# Note: This operation also copies the file to `dest` as a side effect.
38+
subprocess.run([*rsync_argv('-a', f'--write-batch={batch_file}'), f'{src}/', f'{dest}/'], check=True)
39+
40+
# must wipe and recreate the destination directory so the test can
41+
# properly prove that --read-batch recreates the files from scratch.
42+
rmtree(dest)
43+
makepath(dest)
44+
45+
# 3. Now we can test reading it via bash process substitution
46+
rsync_base_cmd = shlex.join(rsync_argv('-a'))
47+
batch_path = shlex.quote(str(batch_file))
48+
dest_path = shlex.quote(str(dest) + '/')
49+
50+
# Construct the bash command: rsync -a --read-batch=<(cat /path/to/batch) /dest/
51+
bash_script = f"{rsync_base_cmd} --read-batch=<(cat {batch_path}) {dest_path}"
52+
53+
try:
54+
proc_read = subprocess.run(
55+
[bash, '-c', bash_script],
56+
capture_output=True,
57+
text=True,
58+
timeout=10,
59+
)
60+
except subprocess.TimeoutExpired:
61+
rmtree(base)
62+
test_fail('process substitution batch test timed out')
63+
64+
ctx = f'rc={proc_read.returncode}, stderr={proc_read.stderr.strip()!r}'
65+
66+
# Evaluate result against the strict S_ISREG check bug
67+
if proc_read.returncode != 0:
68+
rmtree(base)
69+
test_fail(f'rsync crashed reading batch file from pipe ({ctx})')
70+
71+
if not (dest / 'payload.txt').is_file():
72+
rmtree(base)
73+
test_fail(f'rsync exited successfully but payload is missing in target ({ctx})')
74+
75+
rmtree(base)
76+
print('rsync successfully parsed batch stream via process substitution pseudo-path')
77+
raise SystemExit(0)

testsuite/skiplist/cygwin.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ partial-protected-regular-retry-linux
5252
partial-protected-regular-retry-policy # deterministic partial EACCES recovery uses dyld interposing
5353
password-file-symlink
5454
protected-regular
55+
<<<<<<< HEAD
5556
pseudo-paths
57+
read-batch-pipe
5658
rename-mixed-parent-transfer
5759
rrsync-sender-leaf-flip
5860
rrsync-sender-parent-pin

testsuite/skiplist/macos.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ open-noatime
2222
partial-protected-regular-retry-linux
2323
preallocate
2424
protected-regular
25+
<<<<<<< HEAD
2526
pseudo-paths # dynamically skips on runners lacking bash process substitution
27+
read-batch-pipe
2628
readonly-partial-abort-mode-regression #
2729
rrsync-sender-leaf-flip
2830
rrsync-sender-parent-pin

0 commit comments

Comments
 (0)