#!/bin/sh
#
# Obnam verification test.
#
# This script runs and verifies backups with Obnam. There are two stages.
# In the first stage, the user makes backups frequently for some period
# of time (e.g., daily for a week). In the second stage, every backup
# generation is restored and the restored data compared with the original.
# The test succeeds if all generations can be restored and verified
# successfully.
#
# The verification is done using the summain(1) checksumming and manifest
# generation tool. Obnam has an internal verification command, but it is
# better to use an independent tool. summain(1) is a better choice than,
# say, md5sum, since it includes much of the inode metadata in the manifest,
# so that restoring file permissions, etc, are also verified.
#
# To use this script, run it one the following ways:
#
#   ./verification-test backup REPO DIR
#   ./verification-test verify REPO DIR
#
# You can optionally add the name of a configuration file to use as the
# fourth argument.
#
# You must run this script from the Obnam source directory.
# The repository must be a local directory.
# You can choose any DIR you like, but it should be something that changes
# frequently and is small enough that you don't get impatient about while
# it is getting backed up.
#
# The filesystem (or the parts inside the specified directory) MUST be
# idle from when the backup start until it ends. Otherwise the test may
# fail even though Obnam was working ine: it's just that some file changed
# between Obnam backing it up and summain including it in the manifest.
#
# Copyright 2011-2014,2017  Lars Wirzenius
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

set -eux

die()
{
    echo "$@" 1>&2
    exit 1
}

backup()
{
    local repo="$1"
    local dir="$2"
    local conf="$3"
    local client=$(awk '/client-name/ { print $3 }' "$conf")
    local genids=$(mktemp)

    ./obnam --no-default-configs --config="$conf" backup || exit 1

    while ! ./obnam --no-default-configs --config="$conf" genids > "$genids"
    do
        :
    done
    local gen=$(tail -n1 "$genids")
    if [ "x$gen" = "x" ]
    then
        die "gen is empty"
    fi
    summain "$dir" -r --output="$repo/$client.$gen.summain" -c SHA1
}

abspath()
{
    case "$1" in
        /*) echo -n "$1" ;;
        *) echo -n "$(pwd)/$1" ;;
    esac
}

verify()
{
    local repo="$1"
    local dir=$(abspath "$2")
    local conf="$3"
    local tempdir="$(mktemp -d)"
    local client=$(awk '/client-name/ { print $3 }' "$conf")

    ./obnam --no-default-configs --config="$conf" genids \
        > "$tempdir"/gens || exit 42
    while read gen
    do
        rm -rf "$tempdir/$gen"
        ./obnam --no-default-configs --config="$conf" \
            restore --to="$tempdir/$gen" --generation="$gen" || \
            exit 42
        summain "$tempdir/$gen/$dir" -r --output="$tempdir/summain.$gen" \
                -c SHA1
        if ! diff -u "$repo/$client.$gen.summain" "$tempdir/summain.$gen"
        then
            die "generation $gen failed to restore properly, see $tempdir"
        fi
        rm -rf "$tempdir/$gen" "$tempdir/summain.$gen"
    done < "$tempdir/gens"
    rm -rf "$tempdir"
}

[ "$#" = 4 ] || die "Bad usage, read source!"

repo="$2"
root="$3"
conf="$4"

case "$1" in
     backup)
        backup "$repo" "$root" "$conf"
        ;;
     verify)
        verify "$repo" "$root" "$conf"
        ;;
     *)
        die "Unknown subcommand $1"
        ;;
esac

