rsync testsuite
Rsync's automated tests live here. Bug fixes should include a regression test when practical.
Layout
testsuite/tests/contains the test scripts. Test names end in_test.pytestsuite/runtests.pydiscovers and runs teststestsuite/rsyncfns.pycontains the legacy test helperstestsuite/harness/contains metadata, profile, result and receipt supporttestsuite/profiles/records platform capabilities and peer deviationstestsuite/fleettest.pyruns the suite across the maintainer fleettestsuite/abdiff.pycompares two rsync versions over the same transfers- COVERAGE.md records option and daemon-parameter coverage
Some tests also use C helpers built with rsync.
Writing tests
A regression test should assert the behaviour being fixed. A final source and destination comparison can miss the actual bug.
Function-based tests use one @requires(...) decorator. Existing module tests use one top-level metadata(...) call while they are migrated. Declare any capability passed to test_skipped() and use require_tcp() or require_asan() for those checks.
Use TestContext or the existing rsyncfns.py paths for scratch data. Do not write into the source tree or use sleeps for synchronisation and timestamp changes. Tests run in parallel by default and must clean up their processes, sockets and temporary files. Use write_daemon_conf() or build_rsyncd_conf() for ordinary daemon configurations.
Running tests
Run the standard suite from a configured build directory:
make check
Other make targets:
make check CHECK_J=1
make check29
make check30
make check-progs
make installcheck
make coverage-all
The runner accepts names and shell patterns:
./testsuite/runtests.py
./testsuite/runtests.py chmod-temp-dir
./testsuite/runtests.py 'xattr*'
The main controls are -j, --rsync-bin, --rsync-bin2, --protocol, --profiles, --use-tcp, --race-timeout, --receipt, --describe-tests and --valgrind. Run ./testsuite/runtests.py --help for the full list.
TCP daemon mode
--use-tcp starts unauthenticated test daemons on loopback addresses and some fixtures enable unsafe daemon options. Other local users can reach those listeners, so use the default pipe transport on shared hosts.
Results and profiles
| Result | Meaning |
|---|---|
| PASS | The assertion passed |
| FAIL | The assertion failed |
| ERROR | The test environment or harness failed |
| SKIP | The test did not run |
| UNSUPPORTED | A declared capability was unavailable |
| XFAIL | A known defect reproduced |
| XPASS | A known defect no longer reproduced |
| PROFILE_ERROR | The result disagreed with the active profile |
Exit codes are 0 for pass, 1 for fail, 2 for error, 77 for skip and 78 for expected failure.
Profiles compose by name. For example --profiles=linux,peer-3.4.1 combines the Linux capabilities with the known deviations for that peer. Tests tagged version-mix are selected from metadata.
An unsupported result is accepted only when the test declares the capability and the active profile permits its absence. A generic skip is a profile error. Receipts retain the raw outcome and the profile verdict.
Scratch data and requirements
Tests use testtmp/<name>/; failed scratch directories remain for inspection. The suite needs Python 3, /bin/sh and the normal build toolchain. ACL and extended-attribute tests also need the platform ACL and attr tools.
Fleet testing
testsuite/fleettest.py builds the committed revision on configured hosts and runs the same pipe, TCP, protocol and non-root lanes used by CI. Profiled passes validate their receipts. A target mapped to a workflow matrix declares its selected profiles in the fleet configuration. Configuration is read from ~/.fleettest.json then testsuite/fleettest.json or from the path passed to --fleet.
Start with the checked-in example:
cp testsuite/fleettest.json.example testsuite/fleettest.json
Common commands:
python3 testsuite/fleettest.py
python3 testsuite/fleettest.py --list
python3 testsuite/fleettest.py --targets freebsd,netbsd
python3 testsuite/fleettest.py --keep-on-fail
Target-specific skip allowances require a matching unsupported capability. Non-root and protocol passes are declared in the target entry. Do not point TCP fleet runs at shared hosts.
Differential testing
testsuite/abdiff.py runs the same transfer with two rsync binaries and compares the result, diagnostics, file data, metadata and optional peak memory.
Examples:
testsuite/abdiff.py
testsuite/abdiff.py --sweep all -j5
testsuite/abdiff.py --loop --timelimit 3600 --cost
The available transports are local copy, support/lsh.sh, a pipe daemon, a TCP daemon and rrsync. Pair each binary with the matching rrsync script when testing that transport.
Historical binaries live in old_versions/ -- Investigate differences and confirm the intended behaviour before adding a focused test under testsuite/tests/