2015-07-18 21:19:50 +00:00
|
|
|
// +build !openbsd
|
2015-08-17 09:02:04 +00:00
|
|
|
// +build !windows
|
2015-07-18 21:19:50 +00:00
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2016-09-18 16:13:39 +00:00
|
|
|
"fmt"
|
2015-07-18 21:19:50 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2016-02-14 14:29:28 +00:00
|
|
|
"restic"
|
|
|
|
"restic/repository"
|
|
|
|
. "restic/test"
|
2015-07-18 21:19:50 +00:00
|
|
|
)
|
|
|
|
|
2015-07-19 20:53:10 +00:00
|
|
|
const (
|
|
|
|
mountWait = 20
|
|
|
|
mountSleep = 100 * time.Millisecond
|
|
|
|
mountTestSubdir = "snapshots"
|
|
|
|
)
|
|
|
|
|
2016-09-15 19:17:20 +00:00
|
|
|
func snapshotsDirExists(t testing.TB, dir string) bool {
|
|
|
|
f, err := os.Open(filepath.Join(dir, mountTestSubdir))
|
|
|
|
if err != nil && os.IsNotExist(err) {
|
|
|
|
return false
|
|
|
|
}
|
2015-07-19 20:53:10 +00:00
|
|
|
|
2016-09-15 19:17:20 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
2015-07-19 20:53:10 +00:00
|
|
|
|
2016-09-15 19:17:20 +00:00
|
|
|
if err := f.Close(); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
2015-07-19 20:53:10 +00:00
|
|
|
|
2016-09-15 19:17:20 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// waitForMount blocks (max mountWait * mountSleep) until the subdir
|
|
|
|
// "snapshots" appears in the dir.
|
|
|
|
func waitForMount(t testing.TB, dir string) {
|
|
|
|
for i := 0; i < mountWait; i++ {
|
|
|
|
if snapshotsDirExists(t, dir) {
|
|
|
|
t.Log("mounted directory is ready")
|
|
|
|
return
|
2015-07-19 20:53:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(mountSleep)
|
|
|
|
}
|
|
|
|
|
2016-09-15 19:17:20 +00:00
|
|
|
t.Errorf("subdir %q of dir %s never appeared", mountTestSubdir, dir)
|
2015-07-19 20:53:10 +00:00
|
|
|
}
|
2015-07-19 21:02:48 +00:00
|
|
|
|
2016-09-15 19:17:20 +00:00
|
|
|
func mount(t testing.TB, global GlobalOptions, dir string) {
|
|
|
|
cmd := &CmdMount{global: &global}
|
|
|
|
OK(t, cmd.Mount(dir))
|
|
|
|
}
|
2016-01-23 18:10:43 +00:00
|
|
|
|
2016-09-15 19:17:20 +00:00
|
|
|
func umount(t testing.TB, global GlobalOptions, dir string) {
|
|
|
|
cmd := &CmdMount{global: &global}
|
2016-09-15 19:32:15 +00:00
|
|
|
|
|
|
|
var err error
|
|
|
|
for i := 0; i < mountWait; i++ {
|
|
|
|
if err = cmd.Umount(dir); err == nil {
|
|
|
|
t.Logf("directory %v umounted", dir)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(mountSleep)
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Errorf("unable to umount dir %v, last error was: %v", dir, err)
|
2016-09-15 19:17:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func listSnapshots(t testing.TB, dir string) []string {
|
|
|
|
snapshotsDir, err := os.Open(filepath.Join(dir, "snapshots"))
|
|
|
|
OK(t, err)
|
|
|
|
names, err := snapshotsDir.Readdirnames(-1)
|
|
|
|
OK(t, err)
|
|
|
|
OK(t, snapshotsDir.Close())
|
|
|
|
return names
|
2015-07-19 21:02:48 +00:00
|
|
|
}
|
|
|
|
|
2015-07-18 21:19:50 +00:00
|
|
|
func TestMount(t *testing.T) {
|
|
|
|
if !RunFuseTest {
|
|
|
|
t.Skip("Skipping fuse tests")
|
|
|
|
}
|
|
|
|
|
2016-09-15 19:17:20 +00:00
|
|
|
withTestEnvironment(t, func(env *testEnvironment, global GlobalOptions) {
|
|
|
|
checkSnapshots := func(repo *repository.Repository, mountpoint string, snapshotIDs restic.IDs) {
|
|
|
|
t.Logf("checking for %d snapshots: %v", len(snapshotIDs), snapshotIDs)
|
|
|
|
go mount(t, global, mountpoint)
|
|
|
|
waitForMount(t, mountpoint)
|
|
|
|
defer umount(t, global, mountpoint)
|
|
|
|
|
|
|
|
if !snapshotsDirExists(t, mountpoint) {
|
|
|
|
t.Fatal(`virtual directory "snapshots" doesn't exist`)
|
|
|
|
}
|
2015-07-18 21:19:50 +00:00
|
|
|
|
2016-09-15 19:17:20 +00:00
|
|
|
ids := listSnapshots(t, env.repo)
|
|
|
|
t.Logf("found %v snapshots in repo: %v", len(ids), ids)
|
2015-07-19 13:21:21 +00:00
|
|
|
|
2016-09-15 19:17:20 +00:00
|
|
|
namesInSnapshots := listSnapshots(t, mountpoint)
|
|
|
|
t.Logf("found %v snapshots in fuse mount: %v", len(namesInSnapshots), namesInSnapshots)
|
|
|
|
Assert(t,
|
|
|
|
len(namesInSnapshots) == len(snapshotIDs),
|
|
|
|
"Invalid number of snapshots: expected %d, got %d", len(snapshotIDs), len(namesInSnapshots))
|
|
|
|
|
|
|
|
namesMap := make(map[string]bool)
|
|
|
|
for _, name := range namesInSnapshots {
|
|
|
|
namesMap[name] = false
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, id := range snapshotIDs {
|
|
|
|
snapshot, err := restic.LoadSnapshot(repo, id)
|
|
|
|
OK(t, err)
|
2016-09-18 16:13:39 +00:00
|
|
|
|
|
|
|
ts := snapshot.Time.Format(time.RFC3339)
|
|
|
|
present, ok := namesMap[ts]
|
|
|
|
if !ok {
|
|
|
|
t.Errorf("Snapshot %v (%q) isn't present in fuse dir", id.Str(), ts)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 1; present; i++ {
|
|
|
|
ts = fmt.Sprintf("%s-%d", snapshot.Time.Format(time.RFC3339), i)
|
|
|
|
present, ok = namesMap[ts]
|
|
|
|
if !ok {
|
|
|
|
t.Errorf("Snapshot %v (%q) isn't present in fuse dir", id.Str(), ts)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !present {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
namesMap[ts] = true
|
2016-09-15 19:17:20 +00:00
|
|
|
}
|
2016-09-18 16:13:39 +00:00
|
|
|
|
2016-09-15 19:17:20 +00:00
|
|
|
for name, present := range namesMap {
|
|
|
|
Assert(t, present, "Directory %s is present in fuse dir but is not a snapshot", name)
|
|
|
|
}
|
2015-07-18 21:19:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cmdInit(t, global)
|
|
|
|
repo, err := global.OpenRepository()
|
|
|
|
OK(t, err)
|
|
|
|
|
|
|
|
mountpoint, err := ioutil.TempDir(TestTempDir, "restic-test-mount-")
|
|
|
|
OK(t, err)
|
|
|
|
|
|
|
|
// We remove the mountpoint now to check that cmdMount creates it
|
2015-08-18 19:05:49 +00:00
|
|
|
RemoveAll(t, mountpoint)
|
2015-07-18 21:19:50 +00:00
|
|
|
|
2016-09-01 14:04:29 +00:00
|
|
|
checkSnapshots(repo, mountpoint, []restic.ID{})
|
2015-07-18 21:19:50 +00:00
|
|
|
|
2016-09-15 19:17:20 +00:00
|
|
|
SetupTarTestFixture(t, env.testdata, filepath.Join("testdata", "backup-data.tar.gz"))
|
2015-07-18 21:19:50 +00:00
|
|
|
|
|
|
|
// first backup
|
|
|
|
cmdBackup(t, global, []string{env.testdata}, nil)
|
|
|
|
snapshotIDs := cmdList(t, global, "snapshots")
|
|
|
|
Assert(t, len(snapshotIDs) == 1,
|
|
|
|
"expected one snapshot, got %v", snapshotIDs)
|
|
|
|
|
|
|
|
checkSnapshots(repo, mountpoint, snapshotIDs)
|
|
|
|
|
|
|
|
// second backup, implicit incremental
|
|
|
|
cmdBackup(t, global, []string{env.testdata}, nil)
|
|
|
|
snapshotIDs = cmdList(t, global, "snapshots")
|
|
|
|
Assert(t, len(snapshotIDs) == 2,
|
|
|
|
"expected two snapshots, got %v", snapshotIDs)
|
|
|
|
|
|
|
|
checkSnapshots(repo, mountpoint, snapshotIDs)
|
|
|
|
|
|
|
|
// third backup, explicit incremental
|
2015-07-25 15:05:45 +00:00
|
|
|
cmdBackup(t, global, []string{env.testdata}, &snapshotIDs[0])
|
2015-07-18 21:19:50 +00:00
|
|
|
snapshotIDs = cmdList(t, global, "snapshots")
|
|
|
|
Assert(t, len(snapshotIDs) == 3,
|
|
|
|
"expected three snapshots, got %v", snapshotIDs)
|
|
|
|
|
|
|
|
checkSnapshots(repo, mountpoint, snapshotIDs)
|
|
|
|
})
|
|
|
|
}
|