]> arthur.barton.de Git - bup.git/commitdiff
Be more careful when testing that repeated saves can produce the same tree.
authorRob Browning <rlb@defaultvalue.org>
Sat, 5 Oct 2013 01:58:07 +0000 (20:58 -0500)
committerRob Browning <rlb@defaultvalue.org>
Mon, 7 Oct 2013 01:03:00 +0000 (20:03 -0500)
Previously, test.sh would run multiple saves with no intervening
modifications, and check to see that the top-level "save -t" hash
didn't change, but with the addition of metadata this may fail on some
platforms where the test process itself (the save runs, etc.) affects
atime values.  That's because save is pulling the metadata for
unindexed parent directories directly from the filesystem.  And note
that atime is only special here because the test itself may
incidentally alter it -- we would see the same problem if any of the
other metdata for one of the unindexed parent directories changed
during the test run (i.e. mtime, uid, gid, ...).

To fix this, move the relevant test code from test.sh to
test-redundant-saves.sh, and use a newly added subdir-hash tool so
that we can compare the hashes of the roots of the indexed subtrees
instead of the top-level "save -t" hashes, ignoring the unindexed
parents entirely.

Thanks to Robert Edmonds <edmonds@debian.org> for running rc3 through
the Debian buildds which lead to the kFreeBSD test failure that
demonstrated the problem.

Signed-off-by: Rob Browning <rlb@defaultvalue.org>
Makefile
t/subtree-hash [new file with mode: 0755]
t/test-redundant-saves.sh [new file with mode: 0755]
t/test.sh

index d8686ffff74b7d21db68cbb720eb52f87c71a65e..c0310b04b02331bc691ba9e235a7852ba2d8dfef 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -91,6 +91,7 @@ runtests-cmdline: all
        t/test-restore-single-file.sh
        t/test-rm-between-index-and-save.sh
        t/test-command-without-init-fails.sh
+       t/test-redundant-saves.sh
        t/test.sh
 
 stupid:
diff --git a/t/subtree-hash b/t/subtree-hash
new file mode 100755 (executable)
index 0000000..45e727c
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+# Usage: subtree-hash ROOT_HASH [SUBDIR ...]
+
+subtree_hash()
+{
+    root_hash="$1"
+    if test "$#" -eq 1; then
+        echo $root_hash
+    else
+        subdir="$2"
+        subtree_info="$(git ls-tree "$root_hash" | grep -E "   $subdir\$")" || true
+        if test "$(echo "$subtree_info" | wc -l)" -ne 1; then
+            echo "Found more than one matching line in subtree $root_hash" 1>&2
+            return 1
+        fi
+
+        subtree_hash="$(echo "$subtree_info" | cut -d' ' -f 3 | cut -d$'\t' -f 1)" || true
+        if test -z "$subtree_hash"; then
+            echo "Unable to find subtree hash in git output: $subtree_info" 1>&2
+            return 1
+        fi
+
+        shift 2
+        subtree_hash "$subtree_hash" "$@"
+    fi
+}
+
+subtree_hash "$@"
diff --git a/t/test-redundant-saves.sh b/t/test-redundant-saves.sh
new file mode 100755 (executable)
index 0000000..5bf00b1
--- /dev/null
@@ -0,0 +1,57 @@
+#!/usr/bin/env bash
+
+# Test that running save more than once with no other changes produces
+# the exact same tree.
+
+# Note: we can't compare the top-level hash (i.e. the output of "save
+# -t" because that currently pulls the metadata for unindexed parent
+# directories directly from the filesystem, and the relevant atimes
+# may change between runs.  So instead we extract the roots of the
+# indexed trees for comparison via t/subtree-hash.
+
+. ./wvtest-bup.sh
+
+set -eo pipefail
+
+WVSTART 'all'
+
+top="$(pwd)"
+tmpdir="$(wvmktempdir)"
+export BUP_DIR="$tmpdir/bup"
+export GIT_DIR="$BUP_DIR"
+
+bup() { "$top/bup" "$@"; }
+
+mkdir -p "$tmpdir/src"
+mkdir -p "$tmpdir/src/d"
+mkdir -p "$tmpdir/src/d/e"
+touch "$tmpdir/src/"{f,b,a,d}
+touch "$tmpdir/src/d/z"
+
+WVPASS bup init
+WVPASS bup index -u "$tmpdir/src"
+
+declare -a indexed_top
+IFS=/
+indexed_top="${tmpdir##/}"
+indexed_top=(${indexed_top%%/})
+unset IFS
+
+tree1=$(bup save -t "$tmpdir/src") || WVFAIL
+indexed_tree1="$(t/subtree-hash "$tree1" "${indexed_top[@]}" src)"
+
+WVPASSEQ "$(cd "$tmpdir/src" && bup index -m)" ""
+
+tree2=$(bup save -t "$tmpdir/src") || WVFAIL
+indexed_tree2="$(t/subtree-hash "$tree2" "${indexed_top[@]}" src)"
+
+WVPASSEQ "$indexed_tree1" "$indexed_tree2"
+
+WVPASSEQ "$(bup index -s / | grep ^D)" ""
+
+tree3=$(bup save -t /) || WVFAIL
+indexed_tree3="$(t/subtree-hash "$tree3" "${indexed_top[@]}")"
+
+WVPASSEQ "$indexed_tree3" "$indexed_tree3"
+
+rm -rf "$tmpdir"
index 3656689e0343944893ede400951fb84738d12684..83528458dac9fd417d787bc5d279979abbefb4f5 100755 (executable)
--- a/t/test.sh
+++ b/t/test.sh
@@ -123,19 +123,6 @@ WVPASSEQ "$(cd $D && bup index -m)" \
 f
 a
 ./"
-tree1=$(bup save -t $D) || WVFAIL
-WVPASSEQ "$(cd $D && bup index -m)" ""
-tree2=$(bup save -t $D) || WVFAIL
-if ! [[ $(uname) =~ CYGWIN ]]; then
-    # On Cygwin, the access time may change.
-    WVPASSEQ "$tree1" "$tree2"
-fi
-WVPASSEQ "$(bup index -s / | grep ^D)" ""
-tree3=$(bup save -t /) || WVFAIL
-if ! [[ $(uname) =~ CYGWIN ]]; then
-    # On Cygwin, the access time may change.
-    WVPASSEQ "$tree1" "$tree3"
-fi
 WVPASS bup save -r :$BUP_DIR -n r-test $D
 WVFAIL bup save -r :$BUP_DIR/fake/path -n r-test $D
 WVFAIL bup save -r :$BUP_DIR -n r-test $D/fake/path