Files
rsync/testsuite/daemon-refuse_test.py
Andrew Tridgell 1687230672 testsuite: verify destination content/listings in daemon tests
These daemon tests confirmed refusals/exclusions but accepted the allowed
transfers on exit status alone, so a transfer that exited cleanly while moving
nothing would pass:

  daemon-refuse  allowed() imported verify_dirs but never called it; now it
                 confirms the allowed push/pull actually populated the dest.
  daemon-filter  pull()/the incoming push ignored their exit status, and the
                 outgoing-chmod loop iterated only files that exist -- a
                 zero-file pull passed vacuously. Check the codes and require
                 at least one file to have been mode-checked.
  daemon         run_and_check's unused `expected` param is dropped; the
                 hidden-module and glob listings now compare the exact set of
                 listed paths (catching a leaked extra path), replacing the
                 per-path containment check and the dead normalise() helper
                 whose regex never matched the -r listing format anyway.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 07:43:00 +10:00

80 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""Daemon coverage: refuse options (a named option, a wildcard, and the
allow-list negation form).
daemon-refuse-compress_test.py covers the basic case; this widens it to a
different named option, a wildcard pattern, and the "* !a !v" allow-list idiom
documented in rsyncd.conf.5.
"""
import subprocess
from rsyncfns import (
FROMDIR, SCRATCHDIR,
make_tree, makepath, rmtree, rsync_argv, run_rsync, start_test_daemon,
test_fail, verify_dirs, write_daemon_conf,
)
DAEMON_PORT = 12891
src = FROMDIR
rmtree(src)
make_tree(src, depth=3)
deldir = SCRATCHDIR / 'deldest'
makepath(deldir)
conf = write_daemon_conf([
('refuse-delete', {'path': deldir, 'read only': 'no',
'refuse options': 'delete'}),
('refuse-wild', {'path': src, 'read only': 'yes',
'refuse options': 'checksum*'}),
('only-av', {'path': src, 'read only': 'yes',
'refuse options': '* !a !v'}),
])
url = start_test_daemon(conf, DAEMON_PORT)
def refused(args, what):
proc = subprocess.run(rsync_argv(*args),
stdout=subprocess.DEVNULL, stderr=subprocess.PIPE,
text=True)
if proc.returncode == 0:
test_fail(f"{what} was not refused")
return proc.stderr
def allowed(args, what, expected=None, actual=None):
proc = subprocess.run(rsync_argv(*args),
stdout=subprocess.DEVNULL, stderr=subprocess.PIPE,
text=True)
if proc.returncode not in (0, 23):
test_fail(f"{what} was unexpectedly refused: {proc.stderr}")
# A 0/23 exit alone doesn't prove the transfer happened; verify the data
# actually landed for the allowed cases.
if expected is not None:
verify_dirs(expected, actual, label=what)
# --- a named refused option (delete) ----------------------------------------
refused(['-a', '--delete', f'{src}/', f'{url}refuse-delete/'],
"--delete on a refuse=delete module")
allowed(['-a', f'{src}/', f'{url}refuse-delete/'],
"plain push to a refuse=delete module", src, deldir)
# --- a wildcard refused option (checksum*) ----------------------------------
dest = SCRATCHDIR / 'wilddest'
makepath(dest)
refused(['-a', '--checksum', f'{url}refuse-wild/', f'{dest}/'],
"--checksum on a refuse=checksum* module")
# --- the "* !a !v" allow-list: -av allowed, -z refused ----------------------
rmtree(dest)
makepath(dest)
allowed(['-av', f'{url}only-av/', f'{dest}/'], "-av on an allow-list module",
src, dest)
refused(['-avz', f'{url}only-av/', f'{dest}/'],
"-z on an allow-list module")
print("daemon-refuse: named / wildcard / allow-list refuse options verified")