From 96155abbc53c8b7b5ceb976a310aa472e85d3e10 Mon Sep 17 00:00:00 2001 From: Zen Dodd Date: Thu, 8 Oct 2026 15:58:23 +1000 Subject: [PATCH] testsuite: make timestamp fixtures deterministic --- testsuite/alt-dest_test.py | 7 +++--- testsuite/chgrp_test.py | 2 -- testsuite/devices_test.py | 11 +++++++-- testsuite/fuzzy_test.py | 3 --- testsuite/itemize_test.py | 17 ++++++++++---- testsuite/merge_test.py | 4 ---- testsuite/relative_test.py | 3 --- testsuite/symlink-dirlink-basis_test.py | 30 +++++++++++-------------- 8 files changed, 38 insertions(+), 39 deletions(-) diff --git a/testsuite/alt-dest_test.py b/testsuite/alt-dest_test.py index 19bce222..6430339b 100644 --- a/testsuite/alt-dest_test.py +++ b/testsuite/alt-dest_test.py @@ -8,7 +8,6 @@ import os import shutil -import time from rsyncfns import ( CHKDIR, FROMDIR, RSYNC, RSYNC_PEER, SCRATCHDIR, SRCDIR, TMPDIR, TODIR, @@ -36,9 +35,9 @@ run_rsync('-av', '--include=etc-ltr-list', '--include=*/', '--exclude=*', alt3dir.mkdir() (alt3dir / 'likely').write_text("This is a test file\n") -time.sleep(1) -os.utime(FROMDIR / 'dir' / 'text') -os.utime(FROMDIR / 'likely') +for path in (FROMDIR / 'dir' / 'text', FROMDIR / 'likely'): + st = path.stat() + os.utime(path, (st.st_atime, st.st_mtime + 10)) # chkdir: what a vanilla copy would produce, minus /text and etc-ltr-list. run_rsync('-av', '--exclude=/text', '--exclude=etc-ltr-list', diff --git a/testsuite/chgrp_test.py b/testsuite/chgrp_test.py index ad20fc0e..5d43c223 100644 --- a/testsuite/chgrp_test.py +++ b/testsuite/chgrp_test.py @@ -33,6 +33,4 @@ for g in groups: if proc.returncode != 0: test_fail("Can't chgrp") -time.sleep(2) - checkit(['-rtgpvvv', f'{FROMDIR}/', f'{TODIR}/'], FROMDIR, TODIR) diff --git a/testsuite/devices_test.py b/testsuite/devices_test.py index 40c9419a..db4da0b1 100644 --- a/testsuite/devices_test.py +++ b/testsuite/devices_test.py @@ -109,12 +109,19 @@ checkdiff(['-ai', f'{FROMDIR}/block', f'{TODIR}/block2'], checkdiff(['-ai', f'{FROMDIR}/block2', f'{TODIR}/block'], f"cD{all_plus} block2\n") -import time -time.sleep(1) +ref = (TODIR / 'block').stat() +os.utime(FROMDIR / 'block3', (ref.st_atime, ref.st_mtime + 10), + follow_symlinks=False) checkdiff(['-Di', f'{FROMDIR}/block3', f'{TODIR}/block'], f"cDc.T.{dots} block3\n") +for source, destination in ((FROMDIR / 'block', TODIR / 'block'), + (FROMDIR, TODIR)): + st = source.stat() + os.utime(destination, (st.st_atime, st.st_mtime + 10), + follow_symlinks=False) + # Build the expected -aiHvv listing. chkfile_lines = [ f".d..t.{dots} ./", diff --git a/testsuite/fuzzy_test.py b/testsuite/fuzzy_test.py index 03c57301..7cbec0e5 100644 --- a/testsuite/fuzzy_test.py +++ b/testsuite/fuzzy_test.py @@ -6,8 +6,6 @@ # instead of re-transferring (and --delete-delay still removes the stale # basis file at the end). -import time - from rsyncfns import ( FROMDIR, SRCDIR, TODIR, cp_p, cp_touch, run_rsync, test_fail, verify_dirs, ) @@ -18,7 +16,6 @@ TODIR.mkdir(parents=True, exist_ok=True) cp_p(SRCDIR / 'rsync.c', FROMDIR / 'rsync.c') cp_touch(FROMDIR / 'rsync.c', TODIR / 'rsync2.c') -time.sleep(1) # 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 diff --git a/testsuite/itemize_test.py b/testsuite/itemize_test.py index b6a4e895..6d5539f0 100644 --- a/testsuite/itemize_test.py +++ b/testsuite/itemize_test.py @@ -92,14 +92,19 @@ checkdiff(['-iplrH', f'{FROMDIR}/', f'{TODIR}/'], # Re-touch dirs, permute config2 again and replace the symlink target. run_rsync('-a', '-f', '-! */', f'{FROMDIR}/', str(TODIR)) cp_p(SRCDIR / 'config.sub', FROMDIR / 'foo' / 'config2') -import time -time.sleep(1) # to provoke a directory mtime change below (TODIR / 'foo' / 'sym').unlink() old_umask = os.umask(0) try: os.symlink('../bar/baz', TODIR / 'foo' / 'sym') finally: os.umask(old_umask) +src_foo = (FROMDIR / 'foo').stat() +os.utime(TODIR / 'foo', (src_foo.st_atime, src_foo.st_mtime + 10)) +if symtimes_supported: + src_sym = os.stat(FROMDIR / 'foo' / 'sym', follow_symlinks=False) + os.utime(TODIR / 'foo' / 'sym', + (src_sym.st_atime, src_sym.st_mtime + 10), + follow_symlinks=False) os.chmod(FROMDIR / 'foo' / 'config2', 0o600) os.chmod(TODIR / 'bar' / 'baz' / 'rsync', 0o777) @@ -141,13 +146,17 @@ checkdiff(['-ivvplrtH', f'{FROMDIR}/', f'{TODIR}/'], # Permute one perm and re-touch a file; expect just those two itemizes. os.chmod(TODIR / 'foo' / 'config1', 0o757) -(TODIR / 'foo' / 'config2').touch() +src_config2 = (FROMDIR / 'foo' / 'config2').stat() +os.utime(TODIR / 'foo' / 'config2', + (src_config2.st_atime, src_config2.st_mtime + 10)) checkdiff(['-vplrtH', f'{FROMDIR}/', f'{TODIR}/'], "foo/config2\n", filter=v_filt) os.chmod(TODIR / 'foo' / 'config1', 0o757) -(TODIR / 'foo' / 'config2').touch() +src_config2 = (FROMDIR / 'foo' / 'config2').stat() +os.utime(TODIR / 'foo' / 'config2', + (src_config2.st_atime, src_config2.st_mtime + 10)) checkdiff(['-iplrtH', f'{FROMDIR}/', f'{TODIR}/'], f".f...p{dots} foo/config1\n" f">f..t.{dots} foo/config2\n") diff --git a/testsuite/merge_test.py b/testsuite/merge_test.py index 069a74bb..dc04609d 100644 --- a/testsuite/merge_test.py +++ b/testsuite/merge_test.py @@ -7,7 +7,6 @@ # the canonical case. import os -import time from rsyncfns import ( CHKDIR, TMPDIR, TODIR, @@ -71,9 +70,6 @@ for src in ('from2/sub1/uno', 'from3/sub1/dos', 'from2/sub1/tres'): cp_touch(src, str(CHKDIR / 'sub1')) cp_touch('from3/sub2/subby', str(CHKDIR / 'sub2')) -# Make sure time has moved on before the rsync runs. -time.sleep(1) - # Pre-sync directory-only updates to flatten directory-time differences, # matching the shell test's --existing -f 'exclude,! */' preparation. def _flatten_dirs(src, dst): diff --git a/testsuite/relative_test.py b/testsuite/relative_test.py index 123189c1..39639c43 100644 --- a/testsuite/relative_test.py +++ b/testsuite/relative_test.py @@ -8,7 +8,6 @@ import os import subprocess -import time from rsyncfns import ( CHKDIR, FROMDIR, OUTFILE, TMPDIR, TODIR, @@ -52,8 +51,6 @@ os.chdir(FROMDIR) run_rsync('-ai', '--include=/down/', '--exclude=/*', f'{FROMDIR}/', f'{CHKDIR}/') -time.sleep(1) - print("Test basic relative:") checkit(['-avR', f'./{deepstr}', str(TODIR)], CHKDIR, TODIR) diff --git a/testsuite/symlink-dirlink-basis_test.py b/testsuite/symlink-dirlink-basis_test.py index ffe368e2..c059a210 100644 --- a/testsuite/symlink-dirlink-basis_test.py +++ b/testsuite/symlink-dirlink-basis_test.py @@ -15,7 +15,6 @@ import filecmp import os import subprocess -import time from rsyncfns import ( RSYNC, SCRATCHDIR, RSYNC_PEER, SRCDIR, TMPDIR, @@ -42,6 +41,11 @@ def make_testfile(path) -> None: make_data_file(path, 32768) +def advance_mtime(path) -> None: + st = path.stat() + os.utime(path, (st.st_atime, st.st_mtime + 10)) + + def push(*args, label: str) -> None: # --rsync-path goes BEFORE the positional source/dest args, matching # the shell test's order. With it at the end rsync mis-classifies @@ -79,8 +83,7 @@ assert_same("test 1 initial", srcbase / 'dir' / 'file', home / 'real-dir' / 'fil # Trigger delta transfer. with open(srcbase / 'dir' / 'file', 'ab') as f: f.write(b"appended update\n") -time.sleep(1) -(srcbase / 'dir' / 'file').touch() +advance_mtime(srcbase / 'dir' / 'file') push('-KRlptv', 'dir/file', 'localhost:', label="test 1 update") assert_same("test 1 update", srcbase / 'dir' / 'file', home / 'real-dir' / 'file') @@ -89,8 +92,7 @@ assert_same("test 1 update", srcbase / 'dir' / 'file', home / 'real-dir' / 'file # Test 2: compression. with open(srcbase / 'dir' / 'file', 'ab') as f: f.write(b"another line\n") -time.sleep(1) -(srcbase / 'dir' / 'file').touch() +advance_mtime(srcbase / 'dir' / 'file') push('-KRlptzv', 'dir/file', 'localhost:', label="test 2") assert_same("test 2", srcbase / 'dir' / 'file', home / 'real-dir' / 'file') @@ -107,8 +109,7 @@ push('-KRlptv', 'nested/sub/data.txt', 'localhost:', label="test 3 initial") with open(srcbase / 'nested' / 'sub' / 'data.txt', 'ab') as f: f.write(b"appended nested\n") -time.sleep(1) -(srcbase / 'nested' / 'sub' / 'data.txt').touch() +advance_mtime(srcbase / 'nested' / 'sub' / 'data.txt') push('-KRlptv', 'nested/sub/data.txt', 'localhost:', label="test 3 update") assert_same("test 3 update", @@ -126,8 +127,7 @@ push('-KRlptv', 'dir/file', 'localhost:', label="test 4 initial") old_content = (srcbase / 'dir' / 'file').read_bytes() # the backup should hold this with open(srcbase / 'dir' / 'file', 'ab') as f: f.write(b"backup update\n") -time.sleep(1) -(srcbase / 'dir' / 'file').touch() +advance_mtime(srcbase / 'dir' / 'file') push('-KRlptv', '--backup', 'dir/file', 'localhost:', label="test 4 update") assert_same("test 4 update", srcbase / 'dir' / 'file', home / 'real-dir' / 'file') @@ -147,8 +147,7 @@ push('-KRlptv', '--inplace', 'dir/file', 'localhost:', label="test 5 initial") with open(srcbase / 'dir' / 'file', 'ab') as f: f.write(b"inplace update\n") -time.sleep(1) -(srcbase / 'dir' / 'file').touch() +advance_mtime(srcbase / 'dir' / 'file') push('-KRlptv', '--inplace', 'dir/file', 'localhost:', label="test 5 update") assert_same("test 5 update", srcbase / 'dir' / 'file', home / 'real-dir' / 'file') @@ -162,8 +161,7 @@ push('-Rlptv', 'topfile', 'localhost:', label="test 6 initial") with open(srcbase / 'topfile', 'ab') as f: f.write(b"toplevel update\n") -time.sleep(1) -(srcbase / 'topfile').touch() +advance_mtime(srcbase / 'topfile') push('-Rlptv', 'topfile', 'localhost:', label="test 6 update") assert_same("test 6 update", srcbase / 'topfile', home / 'topfile') @@ -178,8 +176,7 @@ push('-KRlptv', '--protocol=28', '--partial-dir=.rsync-partial', with open(srcbase / 'dir' / 'file', 'ab') as f: f.write(b"partial-dir update\n") -time.sleep(1) -(srcbase / 'dir' / 'file').touch() +advance_mtime(srcbase / 'dir' / 'file') push('-KRlptv', '--protocol=28', '--partial-dir=.rsync-partial', 'dir/file', 'localhost:', label="test 7 update") @@ -194,8 +191,7 @@ push('-KRlptv', '--protocol=28', 'dir/file', 'localhost:', label="test 8 initial with open(srcbase / 'dir' / 'file', 'ab') as f: f.write(b"proto28 update\n") -time.sleep(1) -(srcbase / 'dir' / 'file').touch() +advance_mtime(srcbase / 'dir' / 'file') push('-KRlptv', '--protocol=28', 'dir/file', 'localhost:', label="test 8 update") assert_same("test 8 update", srcbase / 'dir' / 'file', home / 'real-dir' / 'file')