forked from TrueCloudLab/restic
Test pipe walker for invalid paths
It was discovered that when restic is instructed to save `/`, the tree structures in the repository contain an invalid node. When saving the dir `/home/user`, the following structure is created: snapshot -> tree nodes: ["user"] [...] When the root directory `/` is saved, the structure is as follows: snapshot -> tree nodes: ["/"] [...] This behavior is caused by the walker in pipe.go sending a node with the name "." to the archiver, so this commit adds a test for invalid node names.
This commit is contained in:
parent
0535490618
commit
604c27f001
1 changed files with 94 additions and 0 deletions
|
@ -4,6 +4,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -421,6 +422,7 @@ func TestPipelineWalkerMultiple(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
paths, err := filepath.Glob(filepath.Join(TestWalkerPath, "*"))
|
paths, err := filepath.Glob(filepath.Join(TestWalkerPath, "*"))
|
||||||
|
OK(t, err)
|
||||||
|
|
||||||
before, err := statPath(TestWalkerPath)
|
before, err := statPath(TestWalkerPath)
|
||||||
OK(t, err)
|
OK(t, err)
|
||||||
|
@ -491,3 +493,95 @@ func TestPipelineWalkerMultiple(t *testing.T) {
|
||||||
|
|
||||||
Assert(t, before == after, "stats do not match, expected %v, got %v", before, after)
|
Assert(t, before == after, "stats do not match, expected %v, got %v", before, after)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dirsInPath(path string) int {
|
||||||
|
if path == "/" || path == "." || path == "" {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
n := 0
|
||||||
|
for dir := path; dir != "/" && dir != "."; dir = filepath.Dir(dir) {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPipeWalkerRoot(t *testing.T) {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
t.Skipf("not running TestPipeWalkerRoot on %s", runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cwd, err := os.Getwd()
|
||||||
|
OK(t, err)
|
||||||
|
|
||||||
|
testPaths := []string{
|
||||||
|
string(filepath.Separator),
|
||||||
|
".",
|
||||||
|
cwd,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, path := range testPaths {
|
||||||
|
testPipeWalkerRootWithPath(path, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPipeWalkerRootWithPath(path string, t *testing.T) {
|
||||||
|
pattern := filepath.Join(path, "*")
|
||||||
|
rootPaths, err := filepath.Glob(pattern)
|
||||||
|
OK(t, err)
|
||||||
|
|
||||||
|
for i, p := range rootPaths {
|
||||||
|
rootPaths[i], err = filepath.Rel(path, p)
|
||||||
|
OK(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("paths in %v (pattern %q) expanded to %v items", path, pattern, len(rootPaths))
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
defer close(done)
|
||||||
|
|
||||||
|
jobCh := make(chan pipe.Job)
|
||||||
|
var jobs []pipe.Job
|
||||||
|
|
||||||
|
worker := func(wg *sync.WaitGroup) {
|
||||||
|
defer wg.Done()
|
||||||
|
for job := range jobCh {
|
||||||
|
jobs = append(jobs, job)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go worker(&wg)
|
||||||
|
|
||||||
|
filter := func(p string, fi os.FileInfo) bool {
|
||||||
|
p, err := filepath.Rel(path, p)
|
||||||
|
OK(t, err)
|
||||||
|
return dirsInPath(p) <= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
resCh := make(chan pipe.Result, 1)
|
||||||
|
pipe.Walk([]string{path}, filter, done, jobCh, resCh)
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
t.Logf("received %d jobs", len(jobs))
|
||||||
|
|
||||||
|
for i, job := range jobs[:len(jobs)-1] {
|
||||||
|
path := job.Path()
|
||||||
|
if path == "." || path == ".." || path == string(filepath.Separator) {
|
||||||
|
t.Errorf("job %v has invalid path %q", i, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPath := jobs[len(jobs)-1].Path()
|
||||||
|
if lastPath != "" {
|
||||||
|
t.Errorf("last job has non-empty path %q", lastPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(jobs) < len(rootPaths) {
|
||||||
|
t.Errorf("want at least %v jobs, got %v for path %v\n", len(rootPaths), len(jobs), path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue