github.com/charlievieth/fastwalk@v1.0.3/dirent_test.go (about) 1 //go:build (linux || darwin || freebsd || openbsd || netbsd) && !appengine 2 // +build linux darwin freebsd openbsd netbsd 3 // +build !appengine 4 5 package fastwalk_test 6 7 import ( 8 "io/fs" 9 "os" 10 "path/filepath" 11 "runtime" 12 "sync" 13 "testing" 14 15 "github.com/charlievieth/fastwalk" 16 ) 17 18 func TestDirent(t *testing.T) { 19 tempdir := t.TempDir() 20 21 fileName := filepath.Join(tempdir, "file.txt") 22 if err := writeFile(fileName, "file.txt", 0644); err != nil { 23 t.Fatal(err) 24 } 25 linkName := filepath.Join(tempdir, "link.link") 26 if err := symlink(t, filepath.Base(fileName), linkName); err != nil { 27 t.Fatal(err) 28 } 29 30 // Use fastwalk.Walk to create the dir entries 31 getDirEnts := func(t *testing.T) (linkEnt, fileEnt fs.DirEntry) { 32 err := fastwalk.Walk(nil, tempdir, func(path string, d fs.DirEntry, err error) error { 33 switch path { 34 case linkName: 35 linkEnt = d 36 case fileName: 37 fileEnt = d 38 } 39 return nil 40 }) 41 if err != nil { 42 t.Fatal(err) 43 } 44 if fileEnt == nil || linkEnt == nil { 45 t.Fatal("error walking directory") 46 } 47 return linkEnt, fileEnt 48 } 49 50 t.Run("Lstat", func(t *testing.T) { 51 linkEnt, _ := getDirEnts(t) 52 want, err := os.Lstat(linkName) 53 if err != nil { 54 t.Fatal(err) 55 } 56 got, err := linkEnt.Info() 57 if err != nil { 58 t.Fatal(err) 59 } 60 if !os.SameFile(want, got) { 61 t.Errorf("lstat mismatch\n got:\n%s\nwant:\n%s", 62 fastwalk.FormatFileInfo(got), fastwalk.FormatFileInfo(want)) 63 } 64 }) 65 66 t.Run("Stat", func(t *testing.T) { 67 _, fileEnt := getDirEnts(t) 68 want, err := os.Stat(fileName) 69 if err != nil { 70 t.Fatal(err) 71 } 72 got, err := fastwalk.StatDirEntry(linkName, fileEnt) 73 if err != nil { 74 t.Fatal(err) 75 } 76 if !os.SameFile(want, got) { 77 t.Errorf("lstat mismatch\n got:\n%s\nwant:\n%s", 78 fastwalk.FormatFileInfo(got), fastwalk.FormatFileInfo(want)) 79 } 80 fi, err := fileEnt.Info() 81 if err != nil { 82 t.Fatal(err) 83 } 84 if fi != got { 85 t.Error("failed to return or cache FileInfo") 86 } 87 de := fileEnt.(fastwalk.DirEntry) 88 fi, err = de.Stat() 89 if err != nil { 90 t.Fatal(err) 91 } 92 if fi != got { 93 t.Error("failed to use cached Info result for non-symlink") 94 } 95 }) 96 97 t.Run("Parallel", func(t *testing.T) { 98 testParallel := func(t *testing.T, de fs.DirEntry, fn func() (fs.FileInfo, error)) { 99 numCPU := runtime.NumCPU() 100 101 infos := make([][]fs.FileInfo, numCPU) 102 for i := range infos { 103 infos[i] = make([]fs.FileInfo, 100) 104 } 105 106 // Start all the goroutines at the same time to 107 // maximise the chance of a race 108 start := make(chan struct{}) 109 var wg, ready sync.WaitGroup 110 ready.Add(numCPU) 111 wg.Add(numCPU) 112 for i := 0; i < numCPU; i++ { 113 go func(fis []fs.FileInfo, de fs.DirEntry) { 114 defer wg.Done() 115 ready.Done() 116 <-start 117 for i := range fis { 118 fis[i], _ = de.Info() 119 } 120 }(infos[i], de) 121 } 122 123 ready.Wait() 124 close(start) // start all goroutines at once 125 wg.Wait() 126 127 first := infos[0][0] 128 if first == nil { 129 t.Fatal("failed to stat file:", de.Name()) 130 } 131 for _, fis := range infos { 132 for _, fi := range fis { 133 if fi != first { 134 t.Errorf("Expected the same fs.FileInfo to always "+ 135 "be returned got: %#v want: %#v", fi, first) 136 } 137 } 138 } 139 } 140 141 t.Run("File", func(t *testing.T) { 142 t.Run("Stat", func(t *testing.T) { 143 _, fileEnt := getDirEnts(t) 144 de := fileEnt.(fastwalk.DirEntry) 145 testParallel(t, de, de.Stat) 146 }) 147 t.Run("Lstat", func(t *testing.T) { 148 _, fileEnt := getDirEnts(t) 149 de := fileEnt.(fastwalk.DirEntry) 150 testParallel(t, de, de.Info) 151 }) 152 }) 153 154 t.Run("Link", func(t *testing.T) { 155 t.Run("Stat", func(t *testing.T) { 156 linkEnt, _ := getDirEnts(t) 157 de := linkEnt.(fastwalk.DirEntry) 158 testParallel(t, de, de.Stat) 159 }) 160 t.Run("Lstat", func(t *testing.T) { 161 linkEnt, _ := getDirEnts(t) 162 de := linkEnt.(fastwalk.DirEntry) 163 testParallel(t, de, de.Info) 164 }) 165 }) 166 }) 167 }