From: Andrew Tridgell Date: Sun, 24 May 2026 22:01:11 +0000 (+1000) Subject: testsuite: verify --fuzzy actually selects a basis X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=034a4f3b1ee987772904aa9c23292de23317c994;p=thirdparty%2Frsync.git testsuite: verify --fuzzy actually selects a basis Both fuzzy tests asserted only that the final file content matched, which a full transfer that ignored --fuzzy would also satisfy -- so a broken fuzzy basis selection would pass undetected. Drive rsync directly with --debug=FUZZY and assert the generator reports the expected basis ("fuzzy basis selected for : ", generator.c find_fuzzy): rsync2.c for fuzzy, and the closest-named candidate archive-v1.tar for fuzzy-basis. fuzzy switches from checkit() to a manual run plus verify_dirs() so the output can be captured. Co-Authored-By: Claude Opus 4.7 (1M context) --- diff --git a/testsuite/fuzzy-basis_test.py b/testsuite/fuzzy-basis_test.py index 77889439..d91a3b9e 100644 --- a/testsuite/fuzzy-basis_test.py +++ b/testsuite/fuzzy-basis_test.py @@ -11,7 +11,7 @@ import os from rsyncfns import ( FROMDIR, TODIR, - assert_same, make_data_file, makepath, rmtree, run_rsync, + assert_same, make_data_file, makepath, rmtree, run_rsync, test_fail, ) src = FROMDIR @@ -31,7 +31,15 @@ base = (src / newfile).read_bytes() (TODIR / deepdir / 'archive-old.tar').write_bytes(base[:200_000]) (TODIR / deepdir / 'unrelated.dat').write_bytes(b'nothing alike' * 1000) -run_rsync('-a', '--fuzzy', '--no-whole-file', f'{src}/', f'{TODIR}/') +# Capture --debug=FUZZY: a correct final file alone would also result from a +# full transfer that ignored --fuzzy, so assert the scorer actually chose the +# closest-named candidate (archive-v1.tar) as the basis, not just that bytes match. +proc = run_rsync('-a', '--fuzzy', '--no-whole-file', '--debug=FUZZY', + f'{src}/', f'{TODIR}/', capture_output=True) +want = f'fuzzy basis selected for {newfile}: {os.path.join(deepdir, "archive-v1.tar")}' +if want not in proc.stdout: + test_fail(f"--fuzzy did not score archive-v1.tar as the closest basis; " + f"expected {want!r}, --debug=FUZZY output was:\n{proc.stdout}") assert_same(TODIR / newfile, src / newfile, label='fuzzy result') print("fuzzy-basis: --fuzzy candidate scoring (fuzzy_distance) verified at depth") diff --git a/testsuite/fuzzy_test.py b/testsuite/fuzzy_test.py index 7858fcc2..03c57301 100644 --- a/testsuite/fuzzy_test.py +++ b/testsuite/fuzzy_test.py @@ -8,7 +8,9 @@ import time -from rsyncfns import FROMDIR, SRCDIR, TODIR, checkit, cp_p, cp_touch +from rsyncfns import ( + FROMDIR, SRCDIR, TODIR, cp_p, cp_touch, run_rsync, test_fail, verify_dirs, +) FROMDIR.mkdir(parents=True, exist_ok=True) @@ -18,5 +20,15 @@ cp_p(SRCDIR / 'rsync.c', FROMDIR / 'rsync.c') cp_touch(FROMDIR / 'rsync.c', TODIR / 'rsync2.c') time.sleep(1) -checkit(['-avvi', '--no-whole-file', '--fuzzy', '--delete-delay', - f'{FROMDIR}/', f'{TODIR}/'], FROMDIR, TODIR) +# Drive rsync directly (rather than checkit) so we can capture --debug=FUZZY: +# a final tree match alone would also be produced by a full transfer that +# ignored --fuzzy, so assert the generator actually picked rsync2.c as the +# fuzzy basis for rsync.c (generator.c find_fuzzy / "fuzzy basis selected"). +proc = run_rsync('-avvi', '--no-whole-file', '--fuzzy', '--delete-delay', + '--debug=FUZZY', f'{FROMDIR}/', f'{TODIR}/', + capture_output=True) +if 'fuzzy basis selected for rsync.c: rsync2.c' not in proc.stdout: + test_fail("--fuzzy did not select rsync2.c as the basis for rsync.c; " + f"--debug=FUZZY output was:\n{proc.stdout}") +# ...and --delete-delay still removes the stale basis, leaving TODIR == FROMDIR. +verify_dirs(FROMDIR, TODIR)