mirror of https://go.googlesource.com/go
152 lines
3.0 KiB
Go
152 lines
3.0 KiB
Go
// Copyright 2020 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package fs_test
|
|
|
|
import (
|
|
. "io/fs"
|
|
"os"
|
|
pathpkg "path"
|
|
"path/filepath"
|
|
"reflect"
|
|
"testing"
|
|
"testing/fstest"
|
|
)
|
|
|
|
type Node struct {
|
|
name string
|
|
entries []*Node // nil if the entry is a file
|
|
mark int
|
|
}
|
|
|
|
var tree = &Node{
|
|
"testdata",
|
|
[]*Node{
|
|
{"a", nil, 0},
|
|
{"b", []*Node{}, 0},
|
|
{"c", nil, 0},
|
|
{
|
|
"d",
|
|
[]*Node{
|
|
{"x", nil, 0},
|
|
{"y", []*Node{}, 0},
|
|
{
|
|
"z",
|
|
[]*Node{
|
|
{"u", nil, 0},
|
|
{"v", nil, 0},
|
|
},
|
|
0,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
},
|
|
0,
|
|
}
|
|
|
|
func walkTree(n *Node, path string, f func(path string, n *Node)) {
|
|
f(path, n)
|
|
for _, e := range n.entries {
|
|
walkTree(e, pathpkg.Join(path, e.name), f)
|
|
}
|
|
}
|
|
|
|
func makeTree() FS {
|
|
fsys := fstest.MapFS{}
|
|
walkTree(tree, tree.name, func(path string, n *Node) {
|
|
if n.entries == nil {
|
|
fsys[path] = &fstest.MapFile{}
|
|
} else {
|
|
fsys[path] = &fstest.MapFile{Mode: ModeDir}
|
|
}
|
|
})
|
|
return fsys
|
|
}
|
|
|
|
// Assumes that each node name is unique. Good enough for a test.
|
|
// If clear is true, any incoming error is cleared before return. The errors
|
|
// are always accumulated, though.
|
|
func mark(entry DirEntry, err error, errors *[]error, clear bool) error {
|
|
name := entry.Name()
|
|
walkTree(tree, tree.name, func(path string, n *Node) {
|
|
if n.name == name {
|
|
n.mark++
|
|
}
|
|
})
|
|
if err != nil {
|
|
*errors = append(*errors, err)
|
|
if clear {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func TestWalkDir(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
|
|
origDir, err := os.Getwd()
|
|
if err != nil {
|
|
t.Fatal("finding working dir:", err)
|
|
}
|
|
if err = os.Chdir(tmpDir); err != nil {
|
|
t.Fatal("entering temp dir:", err)
|
|
}
|
|
defer os.Chdir(origDir)
|
|
|
|
fsys := makeTree()
|
|
errors := make([]error, 0, 10)
|
|
clear := true
|
|
markFn := func(path string, entry DirEntry, err error) error {
|
|
return mark(entry, err, &errors, clear)
|
|
}
|
|
// Expect no errors.
|
|
err = WalkDir(fsys, ".", markFn)
|
|
if err != nil {
|
|
t.Fatalf("no error expected, found: %s", err)
|
|
}
|
|
if len(errors) != 0 {
|
|
t.Fatalf("unexpected errors: %s", errors)
|
|
}
|
|
walkTree(tree, tree.name, func(path string, n *Node) {
|
|
if n.mark != 1 {
|
|
t.Errorf("node %s mark = %d; expected 1", path, n.mark)
|
|
}
|
|
n.mark = 0
|
|
})
|
|
}
|
|
|
|
func TestIssue51617(t *testing.T) {
|
|
dir := t.TempDir()
|
|
for _, sub := range []string{"a", filepath.Join("a", "bad"), filepath.Join("a", "next")} {
|
|
if err := os.Mkdir(filepath.Join(dir, sub), 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
bad := filepath.Join(dir, "a", "bad")
|
|
if err := os.Chmod(bad, 0); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Chmod(bad, 0700) // avoid errors on cleanup
|
|
var saw []string
|
|
err := WalkDir(os.DirFS(dir), ".", func(path string, d DirEntry, err error) error {
|
|
if err != nil {
|
|
return filepath.SkipDir
|
|
}
|
|
if d.IsDir() {
|
|
saw = append(saw, path)
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := []string{".", "a", "a/bad", "a/next"}
|
|
if !reflect.DeepEqual(saw, want) {
|
|
t.Errorf("got directories %v, want %v", saw, want)
|
|
}
|
|
}
|