ZTS: switch to rsync for directory diffs

While "diff -r" is the most straightforward way of comparing directory
trees for differences, it has two major issues:

 * File metadata is not compared, which means that subtle bugs may be
   missed even if a test is written that exercises the buggy behaviour.
 * diff(1) doesn't know how to compare special files -- it assumes they
   are always different, which means that a test using diff(1) on
   special files will always fail (resulting in such tests not being
   added).

rsync can be used in a very similar manner to diff (with the -ni flags),
but has the additional benefit of being able to detect and resolve many
more differences between directory trees. In addition, rsync has a
standard set of features and flags while diffs feature set depends on
whether you're using GNU or BSD binutils.

Note that for several of the test cases we expect that file timestamps
will not match. For example, the ctime for a file creation or modify
event is stored in the intent log but not the mtime. Thus when replaying
the log the correct ctime is set but the current mtime is used. This is
the expected behavior, so to prevent these tests from failing, there's a
replay_directory_diff function which ignores those kinds of changes.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
Closes #12588
This commit is contained in:
Aleksa Sarai
2022-03-02 05:05:32 +11:00
committed by GitHub
parent 19229e5f1e
commit 669683c4cb
16 changed files with 149 additions and 68 deletions
@@ -55,24 +55,28 @@ function cleanup
cd $CWD || log_fail "Could not cd $CWD"
fi
snapexists $SNAPFS
if [[ $? -eq 0 ]]; then
log_must zfs destroy $SNAPFS
fi
snapexists $SNAPFS
if [[ $? -eq 0 ]]; then
log_must zfs destroy $SNAPFS
fi
if [[ -e $SNAPDIR ]]; then
log_must rm -rf $SNAPDIR > /dev/null 2>&1
fi
if [[ -e $SNAPDIR ]]; then
log_must rm -rf $SNAPDIR > /dev/null 2>&1
fi
if [[ -e $TESTDIR ]]; then
log_must rm -rf $TESTDIR/* > /dev/null 2>&1
fi
if [[ -e $TESTDIR ]]; then
log_must rm -rf $TESTDIR/* > /dev/null 2>&1
fi
if [[ -d "$SNAPSHOT_TARDIR" ]]; then
log_must rm -rf $SNAPSHOT_TARDIR > /dev/null 2>&1
fi
}
log_assert "Verify an archive of a file system is identical to " \
"an archive of its snapshot."
SNAPSHOT_TARDIR="$(mktemp -d /tmp/zfstests_snapshot_002.XXXXXX)"
log_onexit cleanup
typeset -i COUNT=21
@@ -87,14 +91,13 @@ typeset i=1
while [ $i -lt $COUNT ]; do
log_must file_write -o $OP -f $TESTDIR/file$i \
-b $BLOCKSZ -c $NUM_WRITES -d $DATA
(( i = i + 1 ))
done
log_note "Create a tarball from $TESTDIR contents..."
CWD=$PWD
cd $TESTDIR || log_fail "Could not cd $TESTDIR"
log_must tar cf $TESTDIR/tarball.original.tar file*
log_must tar cf $SNAPSHOT_TARDIR/original.tar .
cd $CWD || log_fail "Could not cd $CWD"
log_note "Create a snapshot and mount it..."
@@ -106,7 +109,7 @@ log_must rm -f $TESTDIR/file* > /dev/null 2>&1
log_note "Create tarball of snapshot..."
CWD=$PWD
cd $SNAPDIR || log_fail "Could not cd $SNAPDIR"
log_must tar cf $TESTDIR/tarball.snapshot.tar file*
log_must tar cf $SNAPSHOT_TARDIR/snapshot.tar .
cd $CWD || log_fail "Could not cd $CWD"
log_must mkdir $TESTDIR/original
@@ -114,16 +117,12 @@ log_must mkdir $TESTDIR/snapshot
CWD=$PWD
cd $TESTDIR/original || log_fail "Could not cd $TESTDIR/original"
log_must tar xf $TESTDIR/tarball.original.tar
log_must tar xf $SNAPSHOT_TARDIR/original.tar
cd $TESTDIR/snapshot || log_fail "Could not cd $TESTDIR/snapshot"
log_must tar xf $TESTDIR/tarball.snapshot.tar
log_must tar xf $SNAPSHOT_TARDIR/snapshot.tar
cd $CWD || log_fail "Could not cd $CWD"
diff -q -r $TESTDIR/original $TESTDIR/snapshot > /dev/null 2>&1
if [[ $? -eq 1 ]]; then
log_fail "Directory structures differ."
fi
log_must directory_diff $TESTDIR/original $TESTDIR/snapshot
log_pass "Directory structures match."
@@ -54,24 +54,28 @@ function cleanup
cd $CWD || log_fail "Could not cd $CWD"
fi
snapexists $SNAPCTR
if [[ $? -eq 0 ]]; then
log_must zfs destroy $SNAPCTR
fi
snapexists $SNAPCTR
if [[ $? -eq 0 ]]; then
log_must zfs destroy $SNAPCTR
fi
if [[ -e $SNAPDIR1 ]]; then
log_must rm -rf $SNAPDIR1 > /dev/null 2>&1
fi
if [[ -e $SNAPDIR1 ]]; then
log_must rm -rf $SNAPDIR1 > /dev/null 2>&1
fi
if [[ -e $TESTDIR1 ]]; then
log_must rm -rf $TESTDIR1/* > /dev/null 2>&1
fi
if [[ -e $TESTDIR1 ]]; then
log_must rm -rf $TESTDIR1/* > /dev/null 2>&1
fi
if [[ -d "$SNAPSHOT_TARDIR" ]]; then
log_must rm -rf $SNAPSHOT_TARDIR > /dev/null 2>&1
fi
}
log_assert "Verify that an archive of a dataset is identical to " \
"an archive of the dataset's snapshot."
SNAPSHOT_TARDIR="$(mktemp -d /tmp/zfstests_snapshot_006.XXXXXX)"
log_onexit cleanup
typeset -i COUNT=21
@@ -85,14 +89,13 @@ typeset i=1
while [ $i -lt $COUNT ]; do
log_must file_write -o $OP -f $TESTDIR1/file$i \
-b $BLOCKSZ -c $NUM_WRITES -d $DATA
(( i = i + 1 ))
done
log_note "Create a tarball from $TESTDIR1 contents..."
CWD=$PWD
cd $TESTDIR1 || log_fail "Could not cd $TESTDIR1"
log_must tar cf $TESTDIR1/tarball.original.tar file*
log_must tar cf $SNAPSHOT_TARDIR/original.tar .
cd $CWD || log_fail "Could not cd $CWD"
log_note "Create a snapshot and mount it..."
@@ -104,7 +107,7 @@ log_must rm -f $TESTDIR1/file* > /dev/null 2>&1
log_note "Create tarball of snapshot..."
CWD=$PWD
cd $SNAPDIR1 || log_fail "Could not cd $SNAPDIR1"
log_must tar cf $TESTDIR1/tarball.snapshot.tar file*
log_must tar cf $SNAPSHOT_TARDIR/snapshot.tar .
cd $CWD || log_fail "Could not cd $CWD"
log_must mkdir $TESTDIR1/original
@@ -112,16 +115,12 @@ log_must mkdir $TESTDIR1/snapshot
CWD=$PWD
cd $TESTDIR1/original || log_fail "Could not cd $TESTDIR1/original"
log_must tar xf $TESTDIR1/tarball.original.tar
log_must tar xf $SNAPSHOT_TARDIR/original.tar
cd $TESTDIR1/snapshot || log_fail "Could not cd $TESTDIR1/snapshot"
log_must tar xf $TESTDIR1/tarball.snapshot.tar
log_must tar xf $SNAPSHOT_TARDIR/snapshot.tar
cd $CWD || log_fail "Could not cd $CWD"
diff -q -r $TESTDIR1/original $TESTDIR1/snapshot > /dev/null 2>&1
if [[ $? -eq 1 ]]; then
log_fail "Directory structures differ."
fi
log_must directory_diff $TESTDIR1/original $TESTDIR1/snapshot
log_pass "Directory structures match."