github.com/nibnait/go-learn@v0.0.0-20220227013611-dfa47ea6d2da/src/pkg/mod/golang.org/x/sys@v0.0.0-20210630005230-0f9fa26af87c/unix/dirent_test.go (about) 1 // Copyright 2019 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 //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris 6 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris 7 8 package unix_test 9 10 import ( 11 "bytes" 12 "fmt" 13 "io/ioutil" 14 "os" 15 "path/filepath" 16 "runtime" 17 "sort" 18 "strconv" 19 "strings" 20 "testing" 21 "unsafe" 22 23 "golang.org/x/sys/unix" 24 ) 25 26 func TestDirent(t *testing.T) { 27 const ( 28 direntBufSize = 2048 29 filenameMinSize = 11 30 ) 31 32 d, err := ioutil.TempDir("", "dirent-test") 33 if err != nil { 34 t.Fatalf("tempdir: %v", err) 35 } 36 defer os.RemoveAll(d) 37 t.Logf("tmpdir: %s", d) 38 39 for i, c := range []byte("0123456789") { 40 name := string(bytes.Repeat([]byte{c}, filenameMinSize+i)) 41 err = ioutil.WriteFile(filepath.Join(d, name), nil, 0644) 42 if err != nil { 43 t.Fatalf("writefile: %v", err) 44 } 45 } 46 47 buf := bytes.Repeat([]byte("DEADBEAF"), direntBufSize/8) 48 fd, err := unix.Open(d, unix.O_RDONLY, 0) 49 if err != nil { 50 t.Fatalf("Open: %v", err) 51 } 52 defer unix.Close(fd) 53 n, err := unix.ReadDirent(fd, buf) 54 if err != nil { 55 t.Fatalf("ReadDirent: %v", err) 56 } 57 buf = buf[:n] 58 59 names := make([]string, 0, 10) 60 for len(buf) > 0 { 61 var bc int 62 bc, _, names = unix.ParseDirent(buf, -1, names) 63 if bc == 0 && len(buf) > 0 { 64 t.Fatal("no progress") 65 } 66 buf = buf[bc:] 67 } 68 69 sort.Strings(names) 70 t.Logf("names: %q", names) 71 72 if len(names) != 10 { 73 t.Errorf("got %d names; expected 10", len(names)) 74 } 75 for i, name := range names { 76 ord, err := strconv.Atoi(name[:1]) 77 if err != nil { 78 t.Fatalf("names[%d] is non-integer %q: %v", i, names[i], err) 79 } 80 if expected := string(strings.Repeat(name[:1], filenameMinSize+ord)); name != expected { 81 t.Errorf("names[%d] is %q (len %d); expected %q (len %d)", i, name, len(name), expected, len(expected)) 82 } 83 } 84 } 85 86 func TestDirentRepeat(t *testing.T) { 87 const N = 100 88 // Note: the size of the buffer is small enough that the loop 89 // below will need to execute multiple times. See issue #31368. 90 size := N * unsafe.Offsetof(unix.Dirent{}.Name) / 4 91 if runtime.GOOS == "freebsd" || runtime.GOOS == "netbsd" { 92 if size < 1024 { 93 size = 1024 // DIRBLKSIZ, see issue 31403. 94 } 95 if runtime.GOOS == "freebsd" { 96 t.Skip("need to fix issue 31416 first") 97 } 98 } 99 100 // Make a directory containing N files 101 d, err := ioutil.TempDir("", "direntRepeat-test") 102 if err != nil { 103 t.Fatalf("tempdir: %v", err) 104 } 105 defer os.RemoveAll(d) 106 107 var files []string 108 for i := 0; i < N; i++ { 109 files = append(files, fmt.Sprintf("file%d", i)) 110 } 111 for _, file := range files { 112 err = ioutil.WriteFile(filepath.Join(d, file), []byte("contents"), 0644) 113 if err != nil { 114 t.Fatalf("writefile: %v", err) 115 } 116 } 117 118 // Read the directory entries using ReadDirent. 119 fd, err := unix.Open(d, unix.O_RDONLY, 0) 120 if err != nil { 121 t.Fatalf("Open: %v", err) 122 } 123 defer unix.Close(fd) 124 var files2 []string 125 for { 126 buf := make([]byte, size) 127 n, err := unix.ReadDirent(fd, buf) 128 if err != nil { 129 t.Fatalf("ReadDirent: %v", err) 130 } 131 if n == 0 { 132 break 133 } 134 buf = buf[:n] 135 for len(buf) > 0 { 136 var consumed int 137 consumed, _, files2 = unix.ParseDirent(buf, -1, files2) 138 if consumed == 0 && len(buf) > 0 { 139 t.Fatal("no progress") 140 } 141 buf = buf[consumed:] 142 } 143 } 144 145 // Check results 146 sort.Strings(files) 147 sort.Strings(files2) 148 if strings.Join(files, "|") != strings.Join(files2, "|") { 149 t.Errorf("bad file list: want\n%q\ngot\n%q", files, files2) 150 } 151 }