mirror of
https://github.com/octoleo/restic.git
synced 2024-11-26 23:06:32 +00:00
af50fe9ac0
Suggested-by: greatroar <>
292 lines
10 KiB
Go
292 lines
10 KiB
Go
//go:build darwin || freebsd || linux
|
|
// +build darwin freebsd linux
|
|
|
|
package fuse
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/restic/restic/internal/restic"
|
|
"github.com/restic/restic/internal/test"
|
|
)
|
|
|
|
func TestPathsFromSn(t *testing.T) {
|
|
id1, _ := restic.ParseID("1234567812345678123456781234567812345678123456781234567812345678")
|
|
time1, _ := time.Parse("2006-01-02T15:04:05", "2021-01-01T00:00:01")
|
|
sn1 := &restic.Snapshot{Hostname: "host", Username: "user", Tags: []string{"tag1", "tag2"}, Time: time1}
|
|
restic.TestSetSnapshotID(t, sn1, id1)
|
|
|
|
var p []string
|
|
var s string
|
|
|
|
p, s = pathsFromSn("ids/%i", "2006-01-02T15:04:05", sn1)
|
|
test.Equals(t, []string{"ids/12345678"}, p)
|
|
test.Equals(t, "", s)
|
|
|
|
p, s = pathsFromSn("snapshots/%T", "2006-01-02T15:04:05", sn1)
|
|
test.Equals(t, []string{"snapshots/"}, p)
|
|
test.Equals(t, "2021-01-01T00:00:01", s)
|
|
|
|
p, s = pathsFromSn("hosts/%h/%T", "2006-01-02T15:04:05", sn1)
|
|
test.Equals(t, []string{"hosts/host/"}, p)
|
|
test.Equals(t, "2021-01-01T00:00:01", s)
|
|
|
|
p, s = pathsFromSn("tags/%t/%T", "2006-01-02T15:04:05", sn1)
|
|
test.Equals(t, []string{"tags/tag1/", "tags/tag2/"}, p)
|
|
test.Equals(t, "2021-01-01T00:00:01", s)
|
|
|
|
p, s = pathsFromSn("users/%u/%T", "2006-01-02T15:04:05", sn1)
|
|
test.Equals(t, []string{"users/user/"}, p)
|
|
test.Equals(t, "2021-01-01T00:00:01", s)
|
|
|
|
p, s = pathsFromSn("longids/%I", "2006-01-02T15:04:05", sn1)
|
|
test.Equals(t, []string{"longids/1234567812345678123456781234567812345678123456781234567812345678"}, p)
|
|
test.Equals(t, "", s)
|
|
|
|
p, s = pathsFromSn("%T/%h", "2006/01/02", sn1)
|
|
test.Equals(t, []string{"2021/01/01/host"}, p)
|
|
test.Equals(t, "", s)
|
|
|
|
p, s = pathsFromSn("%T/%i", "2006/01", sn1)
|
|
test.Equals(t, []string{"2021/01/12345678"}, p)
|
|
test.Equals(t, "", s)
|
|
}
|
|
|
|
func TestMakeDirs(t *testing.T) {
|
|
pathTemplates := []string{"ids/%i", "snapshots/%T", "hosts/%h/%T",
|
|
"tags/%t/%T", "users/%u/%T", "longids/%I", "%T/%h", "%T/%i",
|
|
}
|
|
timeTemplate := "2006/01/02"
|
|
|
|
sds := &SnapshotsDirStructure{
|
|
pathTemplates: pathTemplates,
|
|
timeTemplate: timeTemplate,
|
|
}
|
|
|
|
id0, _ := restic.ParseID("0000000012345678123456781234567812345678123456781234567812345678")
|
|
time0, _ := time.Parse("2006-01-02T15:04:05", "2020-12-31T00:00:01")
|
|
sn0 := &restic.Snapshot{Hostname: "host", Username: "user", Tags: []string{"tag1", "tag2"}, Time: time0}
|
|
restic.TestSetSnapshotID(t, sn0, id0)
|
|
|
|
id1, _ := restic.ParseID("1234567812345678123456781234567812345678123456781234567812345678")
|
|
time1, _ := time.Parse("2006-01-02T15:04:05", "2021-01-01T00:00:01")
|
|
sn1 := &restic.Snapshot{Hostname: "host", Username: "user", Tags: []string{"tag1", "tag2"}, Time: time1}
|
|
restic.TestSetSnapshotID(t, sn1, id1)
|
|
|
|
id2, _ := restic.ParseID("8765432112345678123456781234567812345678123456781234567812345678")
|
|
time2, _ := time.Parse("2006-01-02T15:04:05", "2021-01-01T01:02:03")
|
|
sn2 := &restic.Snapshot{Hostname: "host2", Username: "user2", Tags: []string{"tag2", "tag3", "tag4"}, Time: time2}
|
|
restic.TestSetSnapshotID(t, sn2, id2)
|
|
|
|
id3, _ := restic.ParseID("aaaaaaaa12345678123456781234567812345678123456781234567812345678")
|
|
time3, _ := time.Parse("2006-01-02T15:04:05", "2021-01-01T01:02:03")
|
|
sn3 := &restic.Snapshot{Hostname: "host", Username: "user2", Tags: []string{}, Time: time3}
|
|
restic.TestSetSnapshotID(t, sn3, id3)
|
|
|
|
sds.makeDirs(restic.Snapshots{sn0, sn1, sn2, sn3})
|
|
|
|
expNames := make(map[string]*restic.Snapshot)
|
|
expLatest := make(map[string]string)
|
|
|
|
// entries for sn0
|
|
expNames["/ids/00000000"] = sn0
|
|
expNames["/snapshots/2020/12/31"] = sn0
|
|
expNames["/hosts/host/2020/12/31"] = sn0
|
|
expNames["/tags/tag1/2020/12/31"] = sn0
|
|
expNames["/tags/tag2/2020/12/31"] = sn0
|
|
expNames["/users/user/2020/12/31"] = sn0
|
|
expNames["/longids/0000000012345678123456781234567812345678123456781234567812345678"] = sn0
|
|
expNames["/2020/12/31/host"] = sn0
|
|
expNames["/2020/12/31/00000000"] = sn0
|
|
|
|
// entries for sn1
|
|
expNames["/ids/12345678"] = sn1
|
|
expNames["/snapshots/2021/01/01"] = sn1
|
|
expNames["/hosts/host/2021/01/01"] = sn1
|
|
expNames["/tags/tag1/2021/01/01"] = sn1
|
|
expNames["/tags/tag2/2021/01/01"] = sn1
|
|
expNames["/users/user/2021/01/01"] = sn1
|
|
expNames["/longids/1234567812345678123456781234567812345678123456781234567812345678"] = sn1
|
|
expNames["/2021/01/01/host"] = sn1
|
|
expNames["/2021/01/01/12345678"] = sn1
|
|
|
|
// entries for sn2
|
|
expNames["/ids/87654321"] = sn2
|
|
expNames["/snapshots/2021/01/01-1"] = sn2 // sn1 and sn2 have same time string
|
|
expNames["/hosts/host2/2021/01/01"] = sn2
|
|
expNames["/tags/tag2/2021/01/01-1"] = sn2 // sn1 and sn2 have same time string
|
|
expNames["/tags/tag3/2021/01/01"] = sn2
|
|
expNames["/tags/tag4/2021/01/01"] = sn2
|
|
expNames["/users/user2/2021/01/01"] = sn2
|
|
expNames["/longids/8765432112345678123456781234567812345678123456781234567812345678"] = sn2
|
|
expNames["/2021/01/01/host2"] = sn2
|
|
expNames["/2021/01/01/87654321"] = sn2
|
|
|
|
// entries for sn3
|
|
expNames["/ids/aaaaaaaa"] = sn3
|
|
expNames["/snapshots/2021/01/01-2"] = sn3 // sn1 - sn3 have same time string
|
|
expNames["/hosts/host/2021/01/01-1"] = sn3 // sn1 and sn3 have same time string
|
|
expNames["/users/user2/2021/01/01-1"] = sn3 // sn2 and sn3 have same time string
|
|
expNames["/longids/aaaaaaaa12345678123456781234567812345678123456781234567812345678"] = sn3
|
|
expNames["/2021/01/01/host-1"] = sn3 // sn1 and sn3 have same time string and identical host
|
|
expNames["/2021/01/01/aaaaaaaa"] = sn3
|
|
|
|
// intermediate directories
|
|
// sn0
|
|
expNames["/ids"] = nil
|
|
expNames[""] = nil
|
|
expNames["/snapshots/2020/12"] = nil
|
|
expNames["/snapshots/2020"] = nil
|
|
expNames["/snapshots"] = nil
|
|
expNames["/hosts/host/2020/12"] = nil
|
|
expNames["/hosts/host/2020"] = nil
|
|
expNames["/hosts/host"] = nil
|
|
expNames["/hosts"] = nil
|
|
expNames["/tags/tag1/2020/12"] = nil
|
|
expNames["/tags/tag1/2020"] = nil
|
|
expNames["/tags/tag1"] = nil
|
|
expNames["/tags"] = nil
|
|
expNames["/tags/tag2/2020/12"] = nil
|
|
expNames["/tags/tag2/2020"] = nil
|
|
expNames["/tags/tag2"] = nil
|
|
expNames["/users/user/2020/12"] = nil
|
|
expNames["/users/user/2020"] = nil
|
|
expNames["/users/user"] = nil
|
|
expNames["/users"] = nil
|
|
expNames["/longids"] = nil
|
|
expNames["/2020/12/31"] = nil
|
|
expNames["/2020/12"] = nil
|
|
expNames["/2020"] = nil
|
|
|
|
// sn1
|
|
expNames["/snapshots/2021/01"] = nil
|
|
expNames["/snapshots/2021"] = nil
|
|
expNames["/hosts/host/2021/01"] = nil
|
|
expNames["/hosts/host/2021"] = nil
|
|
expNames["/tags/tag1/2021/01"] = nil
|
|
expNames["/tags/tag1/2021"] = nil
|
|
expNames["/tags/tag2/2021/01"] = nil
|
|
expNames["/tags/tag2/2021"] = nil
|
|
expNames["/users/user/2021/01"] = nil
|
|
expNames["/users/user/2021"] = nil
|
|
expNames["/2021/01/01"] = nil
|
|
expNames["/2021/01"] = nil
|
|
expNames["/2021"] = nil
|
|
|
|
// sn2
|
|
expNames["/hosts/host2/2021/01"] = nil
|
|
expNames["/hosts/host2/2021"] = nil
|
|
expNames["/hosts/host2"] = nil
|
|
expNames["/tags/tag3/2021/01"] = nil
|
|
expNames["/tags/tag3/2021"] = nil
|
|
expNames["/tags/tag3"] = nil
|
|
expNames["/tags/tag4/2021/01"] = nil
|
|
expNames["/tags/tag4/2021"] = nil
|
|
expNames["/tags/tag4"] = nil
|
|
expNames["/users/user2/2021/01"] = nil
|
|
expNames["/users/user2/2021"] = nil
|
|
expNames["/users/user2"] = nil
|
|
|
|
// target snapshots for links
|
|
expNames["/snapshots/latest"] = sn3 // sn1 - sn3 have same time string
|
|
expNames["/hosts/host/latest"] = sn3
|
|
expNames["/hosts/host2/latest"] = sn2
|
|
expNames["/tags/tag1/latest"] = sn1
|
|
expNames["/tags/tag2/latest"] = sn2 // sn1 and sn2 have same time string
|
|
expNames["/tags/tag3/latest"] = sn2
|
|
expNames["/tags/tag4/latest"] = sn2
|
|
expNames["/users/user/latest"] = sn1
|
|
expNames["/users/user2/latest"] = sn3 // sn2 and sn3 have same time string
|
|
|
|
// latest links
|
|
expLatest["/snapshots/latest"] = "2021/01/01-2" // sn1 - sn3 have same time string
|
|
expLatest["/hosts/host/latest"] = "2021/01/01-1"
|
|
expLatest["/hosts/host2/latest"] = "2021/01/01"
|
|
expLatest["/tags/tag1/latest"] = "2021/01/01"
|
|
expLatest["/tags/tag2/latest"] = "2021/01/01-1" // sn1 and sn2 have same time string
|
|
expLatest["/tags/tag3/latest"] = "2021/01/01"
|
|
expLatest["/tags/tag4/latest"] = "2021/01/01"
|
|
expLatest["/users/user/latest"] = "2021/01/01"
|
|
expLatest["/users/user2/latest"] = "2021/01/01-1" // sn2 and sn3 have same time string
|
|
|
|
verifyEntries(t, expNames, expLatest, sds.entries)
|
|
}
|
|
|
|
func verifyEntries(t *testing.T, expNames map[string]*restic.Snapshot, expLatest map[string]string, entries map[string]*MetaDirData) {
|
|
actNames := make(map[string]*restic.Snapshot)
|
|
actLatest := make(map[string]string)
|
|
for path, entry := range entries {
|
|
actNames[path] = entry.snapshot
|
|
if entry.linkTarget != "" {
|
|
actLatest[path] = entry.linkTarget
|
|
}
|
|
}
|
|
|
|
test.Equals(t, expNames, actNames)
|
|
test.Equals(t, expLatest, actLatest)
|
|
|
|
// verify tree integrity
|
|
for path, entry := range entries {
|
|
// check that all children are actually contained in entry.names
|
|
for otherPath := range entries {
|
|
if strings.HasPrefix(otherPath, path+"/") {
|
|
sub := otherPath[len(path)+1:]
|
|
// remaining path does not contain a directory
|
|
test.Assert(t, strings.Contains(sub, "/") || (entry.names != nil && entry.names[sub] != nil), "missing entry %v in %v", sub, path)
|
|
}
|
|
}
|
|
if entry.names == nil {
|
|
continue
|
|
}
|
|
// child entries reference the correct MetaDirData
|
|
for elem, subentry := range entry.names {
|
|
test.Equals(t, entries[path+"/"+elem], subentry)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMakeEmptyDirs(t *testing.T) {
|
|
pathTemplates := []string{"ids/%i", "snapshots/%T", "hosts/%h/%T",
|
|
"tags/%t/%T", "users/%u/%T", "longids/id-%I", "%T/%h", "%T/%i", "id-%i",
|
|
}
|
|
timeTemplate := "2006/01/02"
|
|
|
|
sds := &SnapshotsDirStructure{
|
|
pathTemplates: pathTemplates,
|
|
timeTemplate: timeTemplate,
|
|
}
|
|
sds.makeDirs(restic.Snapshots{})
|
|
|
|
expNames := make(map[string]*restic.Snapshot)
|
|
expLatest := make(map[string]string)
|
|
|
|
// empty entries for dir structure
|
|
expNames["/ids"] = nil
|
|
expNames["/snapshots"] = nil
|
|
expNames["/hosts"] = nil
|
|
expNames["/tags"] = nil
|
|
expNames["/users"] = nil
|
|
expNames["/longids"] = nil
|
|
expNames[""] = nil
|
|
|
|
verifyEntries(t, expNames, expLatest, sds.entries)
|
|
}
|
|
|
|
func TestFilenameFromTag(t *testing.T) {
|
|
for _, c := range []struct {
|
|
tag, filename string
|
|
}{
|
|
{"", "_"},
|
|
{".", "_"},
|
|
{"..", "__"},
|
|
{"%.", "%."},
|
|
{"foo", "foo"},
|
|
{"foo ", "foo "},
|
|
{"foo/bar_baz", "foo_bar_baz"},
|
|
} {
|
|
test.Equals(t, c.filename, filenameFromTag(c.tag))
|
|
}
|
|
}
|