Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / fastwalk / fastwalk_test.go
1 // Copyright 2016 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 fastwalk_test
6
7 import (
8         "bytes"
9         "flag"
10         "fmt"
11         "io/ioutil"
12         "os"
13         "path/filepath"
14         "reflect"
15         "runtime"
16         "sort"
17         "strings"
18         "sync"
19         "testing"
20
21         "golang.org/x/tools/internal/fastwalk"
22 )
23
24 func formatFileModes(m map[string]os.FileMode) string {
25         var keys []string
26         for k := range m {
27                 keys = append(keys, k)
28         }
29         sort.Strings(keys)
30         var buf bytes.Buffer
31         for _, k := range keys {
32                 fmt.Fprintf(&buf, "%-20s: %v\n", k, m[k])
33         }
34         return buf.String()
35 }
36
37 func testFastWalk(t *testing.T, files map[string]string, callback func(path string, typ os.FileMode) error, want map[string]os.FileMode) {
38         tempdir, err := ioutil.TempDir("", "test-fast-walk")
39         if err != nil {
40                 t.Fatal(err)
41         }
42         defer os.RemoveAll(tempdir)
43
44         symlinks := map[string]string{}
45         for path, contents := range files {
46                 file := filepath.Join(tempdir, "/src", path)
47                 if err := os.MkdirAll(filepath.Dir(file), 0755); err != nil {
48                         t.Fatal(err)
49                 }
50                 var err error
51                 if strings.HasPrefix(contents, "LINK:") {
52                         symlinks[file] = filepath.FromSlash(strings.TrimPrefix(contents, "LINK:"))
53                 } else {
54                         err = ioutil.WriteFile(file, []byte(contents), 0644)
55                 }
56                 if err != nil {
57                         t.Fatal(err)
58                 }
59         }
60
61         // Create symlinks after all other files. Otherwise, directory symlinks on
62         // Windows are unusable (see https://golang.org/issue/39183).
63         for file, dst := range symlinks {
64                 err = os.Symlink(dst, file)
65                 if err != nil {
66                         if writeErr := ioutil.WriteFile(file, []byte(dst), 0644); writeErr == nil {
67                                 // Couldn't create symlink, but could write the file.
68                                 // Probably this filesystem doesn't support symlinks.
69                                 // (Perhaps we are on an older Windows and not running as administrator.)
70                                 t.Skipf("skipping because symlinks appear to be unsupported: %v", err)
71                         }
72                 }
73         }
74
75         got := map[string]os.FileMode{}
76         var mu sync.Mutex
77         err = fastwalk.Walk(tempdir, func(path string, typ os.FileMode) error {
78                 mu.Lock()
79                 defer mu.Unlock()
80                 if !strings.HasPrefix(path, tempdir) {
81                         t.Errorf("bogus prefix on %q, expect %q", path, tempdir)
82                 }
83                 key := filepath.ToSlash(strings.TrimPrefix(path, tempdir))
84                 if old, dup := got[key]; dup {
85                         t.Errorf("callback called twice for key %q: %v -> %v", key, old, typ)
86                 }
87                 got[key] = typ
88                 return callback(path, typ)
89         })
90
91         if err != nil {
92                 t.Fatalf("callback returned: %v", err)
93         }
94         if !reflect.DeepEqual(got, want) {
95                 t.Errorf("walk mismatch.\n got:\n%v\nwant:\n%v", formatFileModes(got), formatFileModes(want))
96         }
97 }
98
99 func TestFastWalk_Basic(t *testing.T) {
100         testFastWalk(t, map[string]string{
101                 "foo/foo.go":   "one",
102                 "bar/bar.go":   "two",
103                 "skip/skip.go": "skip",
104         },
105                 func(path string, typ os.FileMode) error {
106                         return nil
107                 },
108                 map[string]os.FileMode{
109                         "":                  os.ModeDir,
110                         "/src":              os.ModeDir,
111                         "/src/bar":          os.ModeDir,
112                         "/src/bar/bar.go":   0,
113                         "/src/foo":          os.ModeDir,
114                         "/src/foo/foo.go":   0,
115                         "/src/skip":         os.ModeDir,
116                         "/src/skip/skip.go": 0,
117                 })
118 }
119
120 func TestFastWalk_LongFileName(t *testing.T) {
121         longFileName := strings.Repeat("x", 255)
122
123         testFastWalk(t, map[string]string{
124                 longFileName: "one",
125         },
126                 func(path string, typ os.FileMode) error {
127                         return nil
128                 },
129                 map[string]os.FileMode{
130                         "":                     os.ModeDir,
131                         "/src":                 os.ModeDir,
132                         "/src/" + longFileName: 0,
133                 },
134         )
135 }
136
137 func TestFastWalk_Symlink(t *testing.T) {
138         testFastWalk(t, map[string]string{
139                 "foo/foo.go":       "one",
140                 "bar/bar.go":       "LINK:../foo/foo.go",
141                 "symdir":           "LINK:foo",
142                 "broken/broken.go": "LINK:../nonexistent",
143         },
144                 func(path string, typ os.FileMode) error {
145                         return nil
146                 },
147                 map[string]os.FileMode{
148                         "":                      os.ModeDir,
149                         "/src":                  os.ModeDir,
150                         "/src/bar":              os.ModeDir,
151                         "/src/bar/bar.go":       os.ModeSymlink,
152                         "/src/foo":              os.ModeDir,
153                         "/src/foo/foo.go":       0,
154                         "/src/symdir":           os.ModeSymlink,
155                         "/src/broken":           os.ModeDir,
156                         "/src/broken/broken.go": os.ModeSymlink,
157                 })
158 }
159
160 func TestFastWalk_SkipDir(t *testing.T) {
161         testFastWalk(t, map[string]string{
162                 "foo/foo.go":   "one",
163                 "bar/bar.go":   "two",
164                 "skip/skip.go": "skip",
165         },
166                 func(path string, typ os.FileMode) error {
167                         if typ == os.ModeDir && strings.HasSuffix(path, "skip") {
168                                 return filepath.SkipDir
169                         }
170                         return nil
171                 },
172                 map[string]os.FileMode{
173                         "":                os.ModeDir,
174                         "/src":            os.ModeDir,
175                         "/src/bar":        os.ModeDir,
176                         "/src/bar/bar.go": 0,
177                         "/src/foo":        os.ModeDir,
178                         "/src/foo/foo.go": 0,
179                         "/src/skip":       os.ModeDir,
180                 })
181 }
182
183 func TestFastWalk_SkipFiles(t *testing.T) {
184         // Directory iteration order is undefined, so there's no way to know
185         // which file to expect until the walk happens. Rather than mess
186         // with the test infrastructure, just mutate want.
187         var mu sync.Mutex
188         want := map[string]os.FileMode{
189                 "":              os.ModeDir,
190                 "/src":          os.ModeDir,
191                 "/src/zzz":      os.ModeDir,
192                 "/src/zzz/c.go": 0,
193         }
194
195         testFastWalk(t, map[string]string{
196                 "a_skipfiles.go": "a",
197                 "b_skipfiles.go": "b",
198                 "zzz/c.go":       "c",
199         },
200                 func(path string, typ os.FileMode) error {
201                         if strings.HasSuffix(path, "_skipfiles.go") {
202                                 mu.Lock()
203                                 defer mu.Unlock()
204                                 want["/src/"+filepath.Base(path)] = 0
205                                 return fastwalk.ErrSkipFiles
206                         }
207                         return nil
208                 },
209                 want)
210         if len(want) != 5 {
211                 t.Errorf("saw too many files: wanted 5, got %v (%v)", len(want), want)
212         }
213 }
214
215 func TestFastWalk_TraverseSymlink(t *testing.T) {
216         testFastWalk(t, map[string]string{
217                 "foo/foo.go":   "one",
218                 "bar/bar.go":   "two",
219                 "skip/skip.go": "skip",
220                 "symdir":       "LINK:foo",
221         },
222                 func(path string, typ os.FileMode) error {
223                         if typ == os.ModeSymlink {
224                                 return fastwalk.ErrTraverseLink
225                         }
226                         return nil
227                 },
228                 map[string]os.FileMode{
229                         "":                   os.ModeDir,
230                         "/src":               os.ModeDir,
231                         "/src/bar":           os.ModeDir,
232                         "/src/bar/bar.go":    0,
233                         "/src/foo":           os.ModeDir,
234                         "/src/foo/foo.go":    0,
235                         "/src/skip":          os.ModeDir,
236                         "/src/skip/skip.go":  0,
237                         "/src/symdir":        os.ModeSymlink,
238                         "/src/symdir/foo.go": 0,
239                 })
240 }
241
242 var benchDir = flag.String("benchdir", runtime.GOROOT(), "The directory to scan for BenchmarkFastWalk")
243
244 func BenchmarkFastWalk(b *testing.B) {
245         b.ReportAllocs()
246         for i := 0; i < b.N; i++ {
247                 err := fastwalk.Walk(*benchDir, func(path string, typ os.FileMode) error { return nil })
248                 if err != nil {
249                         b.Fatal(err)
250                 }
251         }
252 }