gopkg.in/tools/godep.v41@v41.0.0-20151217180337-fe5ce707f879/Godeps/_workspace/src/github.com/kr/fs/walk_test.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package fs_test 6 7 import ( 8 "os" 9 "path/filepath" 10 "runtime" 11 "testing" 12 13 "github.com/tools/godep/Godeps/_workspace/src/github.com/kr/fs" 14 ) 15 16 type PathTest struct { 17 path, result string 18 } 19 20 type Node struct { 21 name string 22 entries []*Node // nil if the entry is a file 23 mark int 24 } 25 26 var tree = &Node{ 27 "testdata", 28 []*Node{ 29 {"a", nil, 0}, 30 {"b", []*Node{}, 0}, 31 {"c", nil, 0}, 32 { 33 "d", 34 []*Node{ 35 {"x", nil, 0}, 36 {"y", []*Node{}, 0}, 37 { 38 "z", 39 []*Node{ 40 {"u", nil, 0}, 41 {"v", nil, 0}, 42 }, 43 0, 44 }, 45 }, 46 0, 47 }, 48 }, 49 0, 50 } 51 52 func walkTree(n *Node, path string, f func(path string, n *Node)) { 53 f(path, n) 54 for _, e := range n.entries { 55 walkTree(e, filepath.Join(path, e.name), f) 56 } 57 } 58 59 func makeTree(t *testing.T) { 60 walkTree(tree, tree.name, func(path string, n *Node) { 61 if n.entries == nil { 62 fd, err := os.Create(path) 63 if err != nil { 64 t.Errorf("makeTree: %v", err) 65 return 66 } 67 fd.Close() 68 } else { 69 os.Mkdir(path, 0770) 70 } 71 }) 72 } 73 74 func markTree(n *Node) { walkTree(n, "", func(path string, n *Node) { n.mark++ }) } 75 76 func checkMarks(t *testing.T, report bool) { 77 walkTree(tree, tree.name, func(path string, n *Node) { 78 if n.mark != 1 && report { 79 t.Errorf("node %s mark = %d; expected 1", path, n.mark) 80 } 81 n.mark = 0 82 }) 83 } 84 85 // Assumes that each node name is unique. Good enough for a test. 86 // If clear is true, any incoming error is cleared before return. The errors 87 // are always accumulated, though. 88 func mark(path string, info os.FileInfo, err error, errors *[]error, clear bool) error { 89 if err != nil { 90 *errors = append(*errors, err) 91 if clear { 92 return nil 93 } 94 return err 95 } 96 name := info.Name() 97 walkTree(tree, tree.name, func(path string, n *Node) { 98 if n.name == name { 99 n.mark++ 100 } 101 }) 102 return nil 103 } 104 105 func TestWalk(t *testing.T) { 106 makeTree(t) 107 errors := make([]error, 0, 10) 108 clear := true 109 markFn := func(walker *fs.Walker) (err error) { 110 for walker.Step() { 111 err = mark(walker.Path(), walker.Stat(), walker.Err(), &errors, clear) 112 if err != nil { 113 break 114 } 115 } 116 return err 117 } 118 // Expect no errors. 119 err := markFn(fs.Walk(tree.name)) 120 if err != nil { 121 t.Fatalf("no error expected, found: %s", err) 122 } 123 if len(errors) != 0 { 124 t.Fatalf("unexpected errors: %s", errors) 125 } 126 checkMarks(t, true) 127 errors = errors[0:0] 128 129 // Test permission errors. Only possible if we're not root 130 // and only on some file systems (AFS, FAT). To avoid errors during 131 // all.bash on those file systems, skip during go test -short. 132 if os.Getuid() > 0 && !testing.Short() { 133 // introduce 2 errors: chmod top-level directories to 0 134 os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0) 135 os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0) 136 137 // 3) capture errors, expect two. 138 // mark respective subtrees manually 139 markTree(tree.entries[1]) 140 markTree(tree.entries[3]) 141 // correct double-marking of directory itself 142 tree.entries[1].mark-- 143 tree.entries[3].mark-- 144 err := markFn(fs.Walk(tree.name)) 145 if err != nil { 146 t.Fatalf("expected no error return from Walk, got %s", err) 147 } 148 if len(errors) != 2 { 149 t.Errorf("expected 2 errors, got %d: %s", len(errors), errors) 150 } 151 // the inaccessible subtrees were marked manually 152 checkMarks(t, true) 153 errors = errors[0:0] 154 155 // 4) capture errors, stop after first error. 156 // mark respective subtrees manually 157 markTree(tree.entries[1]) 158 markTree(tree.entries[3]) 159 // correct double-marking of directory itself 160 tree.entries[1].mark-- 161 tree.entries[3].mark-- 162 clear = false // error will stop processing 163 err = markFn(fs.Walk(tree.name)) 164 if err == nil { 165 t.Fatalf("expected error return from Walk") 166 } 167 if len(errors) != 1 { 168 t.Errorf("expected 1 error, got %d: %s", len(errors), errors) 169 } 170 // the inaccessible subtrees were marked manually 171 checkMarks(t, false) 172 errors = errors[0:0] 173 174 // restore permissions 175 os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0770) 176 os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0770) 177 } 178 179 // cleanup 180 if err := os.RemoveAll(tree.name); err != nil { 181 t.Errorf("removeTree: %v", err) 182 } 183 } 184 185 func TestBug3486(t *testing.T) { // http://code.google.com/p/go/issues/detail?id=3486 186 root, err := filepath.EvalSymlinks(runtime.GOROOT()) 187 if err != nil { 188 t.Fatal(err) 189 } 190 lib := filepath.Join(root, "lib") 191 src := filepath.Join(root, "src") 192 seenSrc := false 193 walker := fs.Walk(root) 194 for walker.Step() { 195 if walker.Err() != nil { 196 t.Fatal(walker.Err()) 197 } 198 199 switch walker.Path() { 200 case lib: 201 walker.SkipDir() 202 case src: 203 seenSrc = true 204 } 205 } 206 if !seenSrc { 207 t.Fatalf("%q not seen", src) 208 } 209 }