mirror of
https://github.com/octoleo/restic.git
synced 2024-12-23 11:28:54 +00:00
Add last integration tests, remove testsuite
This commit is contained in:
parent
43d4558a90
commit
5ae04b6834
@ -534,7 +534,7 @@ func (j archiveJob) Copy() pipe.Job {
|
|||||||
func (arch *Archiver) Snapshot(p *Progress, paths []string, parentID backend.ID) (*Snapshot, backend.ID, error) {
|
func (arch *Archiver) Snapshot(p *Progress, paths []string, parentID backend.ID) (*Snapshot, backend.ID, error) {
|
||||||
debug.Log("Archiver.Snapshot", "start for %v", paths)
|
debug.Log("Archiver.Snapshot", "start for %v", paths)
|
||||||
|
|
||||||
debug.Break("Archiver.Snapshot")
|
debug.RunHook("Archiver.Snapshot", nil)
|
||||||
sort.Strings(paths)
|
sort.Strings(paths)
|
||||||
|
|
||||||
// signal the whole pipeline to stop
|
// signal the whole pipeline to stop
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/restic/restic/backend"
|
"github.com/restic/restic/backend"
|
||||||
|
"github.com/restic/restic/debug"
|
||||||
. "github.com/restic/restic/test"
|
. "github.com/restic/restic/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -175,6 +176,80 @@ func TestBackupNonExistingFile(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBackupMissingFile1(t *testing.T) {
|
||||||
|
withTestEnvironment(t, func(env *testEnvironment, global GlobalOptions) {
|
||||||
|
datafile := filepath.Join("testdata", "backup-data.tar.gz")
|
||||||
|
fd, err := os.Open(datafile)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
t.Skipf("unable to find data file %q, skipping", datafile)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
OK(t, err)
|
||||||
|
OK(t, fd.Close())
|
||||||
|
|
||||||
|
setupTarTestFixture(t, env.testdata, datafile)
|
||||||
|
|
||||||
|
cmdInit(t, global)
|
||||||
|
|
||||||
|
ranHook := false
|
||||||
|
debug.Hook("pipe.walk1", func(context interface{}) {
|
||||||
|
pathname := context.(string)
|
||||||
|
|
||||||
|
if pathname != filepath.Join("testdata", "0", "0", "9") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("in hook, removing test file testdata/0/0/9/37")
|
||||||
|
ranHook = true
|
||||||
|
|
||||||
|
OK(t, os.Remove(filepath.Join(env.testdata, "0", "0", "9", "37")))
|
||||||
|
})
|
||||||
|
|
||||||
|
cmdBackup(t, global, []string{env.testdata}, nil)
|
||||||
|
cmdFsck(t, global)
|
||||||
|
|
||||||
|
Assert(t, ranHook, "hook did not run")
|
||||||
|
debug.RemoveHook("pipe.walk1")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBackupMissingFile2(t *testing.T) {
|
||||||
|
withTestEnvironment(t, func(env *testEnvironment, global GlobalOptions) {
|
||||||
|
datafile := filepath.Join("testdata", "backup-data.tar.gz")
|
||||||
|
fd, err := os.Open(datafile)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
t.Skipf("unable to find data file %q, skipping", datafile)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
OK(t, err)
|
||||||
|
OK(t, fd.Close())
|
||||||
|
|
||||||
|
setupTarTestFixture(t, env.testdata, datafile)
|
||||||
|
|
||||||
|
cmdInit(t, global)
|
||||||
|
|
||||||
|
ranHook := false
|
||||||
|
debug.Hook("pipe.walk2", func(context interface{}) {
|
||||||
|
pathname := context.(string)
|
||||||
|
|
||||||
|
if pathname != filepath.Join("testdata", "0", "0", "9", "37") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("in hook, removing test file testdata/0/0/9/37")
|
||||||
|
ranHook = true
|
||||||
|
|
||||||
|
OK(t, os.Remove(filepath.Join(env.testdata, "0", "0", "9", "37")))
|
||||||
|
})
|
||||||
|
|
||||||
|
cmdBackup(t, global, []string{env.testdata}, nil)
|
||||||
|
cmdFsck(t, global)
|
||||||
|
|
||||||
|
Assert(t, ranHook, "hook did not run")
|
||||||
|
debug.RemoveHook("pipe.walk2")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
incrementalFirstWrite = 20 * 1042 * 1024
|
incrementalFirstWrite = 20 * 1042 * 1024
|
||||||
incrementalSecondWrite = 12 * 1042 * 1024
|
incrementalSecondWrite = 12 * 1042 * 1024
|
||||||
@ -205,15 +280,6 @@ func appendRandomData(filename string, bytes uint) error {
|
|||||||
|
|
||||||
func TestIncrementalBackup(t *testing.T) {
|
func TestIncrementalBackup(t *testing.T) {
|
||||||
withTestEnvironment(t, func(env *testEnvironment, global GlobalOptions) {
|
withTestEnvironment(t, func(env *testEnvironment, global GlobalOptions) {
|
||||||
datafile := filepath.Join("testdata", "backup-data.tar.gz")
|
|
||||||
fd, err := os.Open(datafile)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
t.Skipf("unable to find data file %q, skipping", datafile)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
OK(t, err)
|
|
||||||
OK(t, fd.Close())
|
|
||||||
|
|
||||||
cmdInit(t, global)
|
cmdInit(t, global)
|
||||||
|
|
||||||
datadir := filepath.Join(env.base, "testdata")
|
datadir := filepath.Join(env.base, "testdata")
|
||||||
|
@ -18,7 +18,6 @@ import (
|
|||||||
var opts struct {
|
var opts struct {
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
tags map[string]bool
|
tags map[string]bool
|
||||||
breaks map[string]bool
|
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +28,6 @@ var _ = initDebug()
|
|||||||
func initDebug() bool {
|
func initDebug() bool {
|
||||||
initDebugLogger()
|
initDebugLogger()
|
||||||
initDebugTags()
|
initDebugTags()
|
||||||
initDebugBreaks()
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "debug enabled\n")
|
fmt.Fprintf(os.Stderr, "debug enabled\n")
|
||||||
|
|
||||||
@ -105,25 +103,6 @@ func initDebugTags() {
|
|||||||
fmt.Fprintf(os.Stderr, "debug log enabled for: %v\n", tags)
|
fmt.Fprintf(os.Stderr, "debug log enabled for: %v\n", tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initDebugBreaks() {
|
|
||||||
opts.breaks = make(map[string]bool)
|
|
||||||
|
|
||||||
env := os.Getenv("DEBUG_BREAK")
|
|
||||||
if len(env) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
breaks := []string{}
|
|
||||||
|
|
||||||
for _, tag := range strings.Split(env, ",") {
|
|
||||||
t := strings.TrimSpace(tag)
|
|
||||||
opts.breaks[t] = true
|
|
||||||
breaks = append(breaks, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "debug breaks enabled for: %v\n", breaks)
|
|
||||||
}
|
|
||||||
|
|
||||||
// taken from https://github.com/VividCortex/trace
|
// taken from https://github.com/VividCortex/trace
|
||||||
func goroutineNum() int {
|
func goroutineNum() int {
|
||||||
b := make([]byte, 20)
|
b := make([]byte, 20)
|
||||||
@ -194,38 +173,3 @@ func Log(tag string, f string, args ...interface{}) {
|
|||||||
dbgprint()
|
dbgprint()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Break stops the program if the debug tag is active and the string in tag is
|
|
||||||
// contained in the DEBUG_BREAK environment variable.
|
|
||||||
func Break(tag string) {
|
|
||||||
// check if breaking is enabled
|
|
||||||
if v, ok := opts.breaks[tag]; !ok || !v {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, file, line, _ := runtime.Caller(1)
|
|
||||||
Log("break", "stopping process %d at %s (%v:%v)\n", os.Getpid(), tag, file, line)
|
|
||||||
p, err := os.FindProcess(os.Getpid())
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = p.Signal(syscall.SIGSTOP)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BreakIf stops the program if the debug tag is active and the string in tag
|
|
||||||
// is contained in the DEBUG_BREAK environment variable and the return value of
|
|
||||||
// fn is true.
|
|
||||||
func BreakIf(tag string, fn func() bool) {
|
|
||||||
// check if breaking is enabled
|
|
||||||
if v, ok := opts.breaks[tag]; !ok || !v {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if fn() {
|
|
||||||
Break(tag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -3,7 +3,3 @@
|
|||||||
package debug
|
package debug
|
||||||
|
|
||||||
func Log(tag string, fmt string, args ...interface{}) {}
|
func Log(tag string, fmt string, args ...interface{}) {}
|
||||||
|
|
||||||
func Break(string) {}
|
|
||||||
|
|
||||||
func BreakIf(string, func() bool) {}
|
|
||||||
|
28
debug/hooks.go
Normal file
28
debug/hooks.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// +build !release
|
||||||
|
|
||||||
|
package debug
|
||||||
|
|
||||||
|
var (
|
||||||
|
hooks map[string]func(interface{})
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hooks = make(map[string]func(interface{}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Hook(name string, f func(interface{})) {
|
||||||
|
hooks[name] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunHook(name string, context interface{}) {
|
||||||
|
f, ok := hooks[name]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveHook(name string) {
|
||||||
|
delete(hooks, name)
|
||||||
|
}
|
9
debug/hooks_release.go
Normal file
9
debug/hooks_release.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// +build release
|
||||||
|
|
||||||
|
package debug
|
||||||
|
|
||||||
|
func Hook(name string, f func(interface{})) {}
|
||||||
|
|
||||||
|
func RunHook(name string, context interface{}) {}
|
||||||
|
|
||||||
|
func RemoveHook(name string) {}
|
27
pipe/pipe.go
27
pipe/pipe.go
@ -4,7 +4,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
@ -108,17 +107,7 @@ func walk(basedir, dir string, done chan struct{}, jobs chan<- Job, res chan<- R
|
|||||||
|
|
||||||
// Insert breakpoint to allow testing behaviour with vanishing files
|
// Insert breakpoint to allow testing behaviour with vanishing files
|
||||||
// between Readdir() and lstat()
|
// between Readdir() and lstat()
|
||||||
debug.BreakIf("pipe.walk1", func() bool {
|
debug.RunHook("pipe.walk1", relpath)
|
||||||
match, err := path.Match(os.Getenv("DEBUG_BREAK_PIPE"), relpath)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if match {
|
|
||||||
debug.Log("break", "break pattern matches for %v\n", relpath)
|
|
||||||
}
|
|
||||||
|
|
||||||
return match
|
|
||||||
})
|
|
||||||
|
|
||||||
entries := make([]<-chan Result, 0, len(names))
|
entries := make([]<-chan Result, 0, len(names))
|
||||||
|
|
||||||
@ -140,19 +129,7 @@ func walk(basedir, dir string, done chan struct{}, jobs chan<- Job, res chan<- R
|
|||||||
|
|
||||||
// Insert breakpoint to allow testing behaviour with vanishing files
|
// Insert breakpoint to allow testing behaviour with vanishing files
|
||||||
// between walk and open
|
// between walk and open
|
||||||
debug.BreakIf("pipe.walk2", func() bool {
|
debug.RunHook("pipe.walk2", filepath.Join(relpath, name))
|
||||||
p := filepath.Join(relpath, name)
|
|
||||||
|
|
||||||
match, err := path.Match(os.Getenv("DEBUG_BREAK_PIPE"), p)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if match {
|
|
||||||
debug.Log("break", "break pattern matches for %v\n", p)
|
|
||||||
}
|
|
||||||
|
|
||||||
return match
|
|
||||||
})
|
|
||||||
|
|
||||||
if isDir(fi) {
|
if isDir(fi) {
|
||||||
err = walk(basedir, subpath, done, jobs, ch)
|
err = walk(basedir, subpath, done, jobs, ch)
|
||||||
|
12
testsuite.sh
12
testsuite.sh
@ -1,12 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# tempdir for binaries
|
|
||||||
export BASEDIR="$(mktemp --tmpdir --directory restic-testsuite-XXXXXX)"
|
|
||||||
export DEBUG_LOG="${BASEDIR}/restic.log"
|
|
||||||
|
|
||||||
export TZ=UTC
|
|
||||||
|
|
||||||
echo "restic testsuite basedir ${BASEDIR}"
|
|
||||||
|
|
||||||
# run tests
|
|
||||||
testsuite/run.sh "$@"
|
|
Binary file not shown.
117
testsuite/run.sh
117
testsuite/run.sh
@ -1,117 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
export dir=$(dirname "$0")
|
|
||||||
export fake_data_file="${dir}/fake-data.tar.gz"
|
|
||||||
|
|
||||||
prepare() {
|
|
||||||
export BASE="$(mktemp --tmpdir --directory restic-testsuite-XXXXXX)"
|
|
||||||
export RESTIC_REPOSITORY="${BASE}/restic-backup"
|
|
||||||
export RESTIC_PASSWORD="foobar"
|
|
||||||
export DATADIR="${BASE}/fake-data"
|
|
||||||
debug "repository is at ${RESTIC_REPOSITORY}"
|
|
||||||
|
|
||||||
mkdir -p "$DATADIR"
|
|
||||||
(cd "$DATADIR"; tar xz) < "$fake_data_file"
|
|
||||||
debug "extracted fake data to ${DATADIR}"
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
if [ "$DEBUG" = "1" ]; then
|
|
||||||
debug "leaving dir ${BASE}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -rf "${BASE}"
|
|
||||||
debug "removed dir ${BASE}"
|
|
||||||
unset BASE
|
|
||||||
unset RESTIC_REPOSITORY
|
|
||||||
}
|
|
||||||
|
|
||||||
msg() {
|
|
||||||
printf "%s\n" "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
pass() {
|
|
||||||
printf "\e[32m%s\e[39m\n" "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
err() {
|
|
||||||
printf "\e[31m%s\e[39m\n" "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
debug() {
|
|
||||||
if [ "$DEBUG" = "1" ]; then
|
|
||||||
printf "\e[33m%s\e[39m\n" "$*"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
fail() {
|
|
||||||
err "$@"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
run() {
|
|
||||||
if [ "$DEBUG" = "1" ]; then
|
|
||||||
"$@"
|
|
||||||
else
|
|
||||||
"$@" > /dev/null
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
export -f prepare cleanup msg debug pass err fail run
|
|
||||||
|
|
||||||
if [ -z "$BASEDIR" ]; then
|
|
||||||
echo "BASEDIR not set" >&2
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
which restic > /dev/null || fail "restic binary not found!"
|
|
||||||
which restic.debug > /dev/null || fail "restic.debug binary not found!"
|
|
||||||
which dirdiff > /dev/null || fail "dirdiff binary not found!"
|
|
||||||
|
|
||||||
debug "restic path: $(which restic)"
|
|
||||||
debug "restic.debug path: $(which restic.debug)"
|
|
||||||
debug "dirdiff path: $(which dirdiff)"
|
|
||||||
debug "path: $PATH"
|
|
||||||
|
|
||||||
debug "restic versions:"
|
|
||||||
run restic version
|
|
||||||
run restic.debug version
|
|
||||||
|
|
||||||
if [ "$#" -gt 0 ]; then
|
|
||||||
testfiles="$1"
|
|
||||||
else
|
|
||||||
testfiles=(${dir}/test-*.sh)
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "testfiles: ${testfiles[@]}"
|
|
||||||
|
|
||||||
failed=""
|
|
||||||
for testfile in "${testfiles[@]}"; do
|
|
||||||
msg "================================================================================"
|
|
||||||
msg "run test $testfile"
|
|
||||||
msg ""
|
|
||||||
|
|
||||||
current=$(basename "${testfile}" .sh)
|
|
||||||
|
|
||||||
if [ "$DEBUG" = "1" ]; then
|
|
||||||
OPTS="-v"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if bash $OPTS "${testfile}"; then
|
|
||||||
pass "${current} pass"
|
|
||||||
else
|
|
||||||
err "${current} failed!"
|
|
||||||
failed+=" ${current}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -n "$failed" ]; then
|
|
||||||
err "failed tests: ${failed}"
|
|
||||||
msg "restic versions:"
|
|
||||||
run restic version
|
|
||||||
run restic.debug version
|
|
||||||
exit 1
|
|
||||||
fi
|
|
@ -1,16 +0,0 @@
|
|||||||
set -em
|
|
||||||
|
|
||||||
# setup restic
|
|
||||||
prepare
|
|
||||||
run restic init
|
|
||||||
|
|
||||||
# start backup, break between readdir and lstat
|
|
||||||
DEBUG_BREAK=pipe.walk1 DEBUG_BREAK_PIPE="fake-data/0/0/9" run restic.debug backup "${BASE}/fake-data" && debug "done"
|
|
||||||
|
|
||||||
# remove file
|
|
||||||
rm -f "${BASE}/fake-data/0/0/9/37"
|
|
||||||
|
|
||||||
# resume backup
|
|
||||||
fg
|
|
||||||
|
|
||||||
cleanup
|
|
@ -1,16 +0,0 @@
|
|||||||
set -em
|
|
||||||
|
|
||||||
# setup restic
|
|
||||||
prepare
|
|
||||||
run restic init
|
|
||||||
|
|
||||||
# start backup, break between walk and save
|
|
||||||
DEBUG_BREAK=pipe.walk2 DEBUG_BREAK_PIPE="fake-data/0/0/9/37" run restic.debug backup "${BASE}/fake-data" && debug "done"
|
|
||||||
|
|
||||||
# remove file
|
|
||||||
rm -f "${BASE}/fake-data/0/0/9/37"
|
|
||||||
|
|
||||||
# resume backup
|
|
||||||
fg
|
|
||||||
|
|
||||||
cleanup
|
|
Loading…
Reference in New Issue
Block a user